Add "Tool calls by risk" donut card to the AI Governance dashboard
Builds on the donut chart (Add a reusable donut chart for the AI Governanc... (!256313 - merged)) and the tool calls card (Add the tool calls card, ClickHouse reader and ... (!256578 - merged)), both merged. Verified on GDK with the flags on (screenshots below).
What does this MR do and why?
- Adds the "Tool calls by risk" card to the AI Governance dashboard, built on the donut from Add a reusable donut chart for the AI Governanc... (!256313 - merged).
- Splits the AI tool calls in the selected window into Read, Write, Destructive and Unclassified, with the total in the center and percentages in the legend.
- Adds an experiment
byRisk { total approximate slices { risk count } }field toaiGovernanceToolCalls, behind the sameai_governance_tool_callsflag, which gates the card too and is off by default everywhere. - The card asks for
byRiskonly, so the top tools query does not run for it, and the top tools card does not trigger the risk query.
What we're building and how
What. One card that answers "how risky are the tool calls our AI agents make?". It follows the dashboard's Show control (All agents, DAP, Connected) and date range.
What "risk" means. Each tool's risk is its action type in the tool registry, the same classification the Tool management tab uses for its default permissions (Ai::ToolRules::Registry.action_type_of):
- Read: read-only tools, such as reading an issue or a file.
- Write: tools that change GitLab data or files.
- Destructive: running commands, MCP tools and Git operations.
- MCP tools take their action type from their own read-only and destructive hints.
- Tools the registry does not know are counted as Unclassified.
How it's calculated. The tool calls reader from Add the tool calls card, ClickHouse reader and ... (!256578 - merged) counts ai_tool_invoked events per tool name in ClickHouse for the group or project and window. This MR asks it for every tool name instead of the top 10, then maps each name to its action type and adds the counts up. At most 1,000 distinct tool names are read. Past that, the most used 1,000 are counted and approximate is true.
Data notes
- Counts follow the reader on master:
ai_tool_invokedevents (tool name indetails.tool_name) and, since Count Claude Code tool calls (Count Claude Code tool calls in the AI Governan... (!259239 - merged)) merged,ai_claude_tool_invokedevents (name indetails.name). The top tools card and this card read the same events with the same agent class filter, so their totals agree. - GitLab MCP tools are recorded under the prefixed name the Duo Workflow Service calls them by (
gitlab_search). The card strips that prefix before classifying, so an MCP tool gets the action type the Tool management tab shows for it. - Claude Code's own tool names (Read, Edit, Write, Bash and so on) are not in the tool registry, so those calls count as Unclassified until a mapping lands. Follow-up proposal: Read, Grep, Glob, LS, WebFetch, WebSearch as Read; Edit, MultiEdit, Write, NotebookEdit, TodoWrite as Write; Bash, Task and other agent-spawning tools as Destructive.
Screenshots
GDK, flags on, group view, next to the Top tools card:
| Light | Dark |
|---|---|
![]() |
![]() |
How to set up and validate locally
- Enable ClickHouse for analytics and the flags
ai_governance_dashboardandai_governance_tool_callsfor a group. - Have
ai_tool_invokedevents in ClickHouse for that group, using a mix of registry tools and an unknown MCP tool name. - Open the group's AI Governance dashboard.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.

