Add audit logging for Duo workflow tool call approvals
What does this MR do and why?
Add audit logging for Duo workflow tool call approvals
- Emit a duo_tool_call_approved audit event from UpdateToolCallApprovalsService after a tool call is successfully approved, capturing which tool was approved, by whom, and in which session.
References
Screenshots or screen recordings
| Before | After |
|---|---|
| An endless darkness | ![]() |
How to set up and validate locally
- Check out this feature branch, restart GDK
- Trigger some Duo workflow with tool approvals enabled. You can e.g. ask duo to do something that will trigger an approval like creating a demo issue in one of ur projects.
- When approval dialog shows goto
rails console=>::Ai::DuoWorkflows::Workflow.last.id - Got to the graphql explorer and issue mutation
mutation {
updateDuoWorkflowToolCallApprovals(input: {
workflowId: "gid://gitlab/Ai::DuoWorkflows::Workflow/<ID FROM RAILS CONSOLE>",
toolName: "gitlab_create_issue",
toolCallArgs: "{\"path\": \"foo.rb\", \"content\": \"puts 'bar'\"}"
}) {
workflow {
id
status
}
errors
}
}- Go to group audit events. You should see an event logged like in the screenshot above.
Note
The UpdateDuoWorkflowToolCallApprovals mutation is mounted as an experiment (from %18.9) but appears to be yet be connected to an API surface, it's not yet wired to any frontend component. duo_agentic_chat_state_manager.vue — handles @approve-tool / @deny-tool events => handleApproveToolCall() → calls startWorkflow() which sends an approval field over the WebSocket via streamManager.connect(). The audit code is in place on the backend, but it won't fire until either:
- A frontend component is built that calls the GraphQL mutation, or
- The WebSocket approve/deny path is also wired through UpdateToolCallApprovalsService
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
