Duo should remember command/tool approvals
# Overview Users want Duo to remember their approval decisions for specific tools or commands during a single session, rather than asking for approval every time the same tool is invoked. This is especially problematic during debugging or testing workflows where the same commands run repeatedly. # Proposed solution * As a first iteration, a **hybrid approval granularity model** is being implemented that distinguishes between tool types: * **Safe tools** (grep, find, readFile): Approved at tool level, remembers for all uses * **Dangerous tools** (runCommand, writeFile, editFile, deleteFile): Approved at call level, remembers only exact arguments This approach stores approval decisions in `ChatWorkflowState` with a `remember_approval` boolean flag. When a user approves a dangerous tool like `runCommand("npm install")`, the system stores the exact command signature and only auto-approves that specific command in future calls, not arbitrary shell commands. * Multiple proposals suggest using configuration files as the source of truth: * **MCP configuration** - Leverage `mcp.json` with a `preApprovedTools` field (boolean for all tools or array for specific tools) * **IDE settings** - Allow users to configure allowlists/denylists directly in editor settings, similar to how Cursor and Claude Code implement this * Add telemetry around usage to ensure data-driven decisions are made surrounding what feature is built/ iterated on next. --- :white_check_mark: - Done :construction: - In Progress :white_circle: - Not Started <details> <summary> ### :sparkles: Pre-existing work - Session Approval for MCP Tools </summary> <table> <tr> <th></th> <th>Description</th> <th>Sub Epic / Issues</th> <th>Status</th> <th>Technical Lead</th> </tr> <tr> <td>Implement Scoped Tool Approvals for MCP</td> <td> * Introduce **per-session tool approvals** (keyed by workflowId) and integrate them into reload so each tool’s isApproved reflects: * isApproved = approved-by-config * or, approved-for-this-session </td> <td> https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp/-/work_items/1418+ </td> <td> :white_check_mark: </td> <td> @john-slaughter </td> </tr> <tr> <td>Duo UI updates</td> <td> * The component now supports both simple single-button approval and more advanced split-button approval with multiple permission levels. * This gives users more control over AI tool usage while maintaining backward compatibility with existing implementations. </td> <td> https://gitlab.com/gitlab-org/duo-ui/-/merge_requests/279+ </td> <td> :white_check_mark: </td> <td> @dbernardi </td> </tr> <tr> <td>Integrate and update new UI for Approve for Session</td> <td> * Check the tool name before displaying the approval options UI split button in chat to ensure that when it is not a MCP tool call - users only see the `Approve` button. </td> <td> https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp/-/work_items/1514+ </td> <td> :white_check_mark: </td> <td> @dbernardi </td> </tr> <tr> <td>SPIKE (Client-Side)</td> <td> * A client side approach was spiked end to end as a catalyst for this work. * The approach was decided that it may result in security vulnerabilities and a sever side approach will be implemented. </td> <td> https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp/-/merge_requests/2723+ https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/merge_requests/4235+ </td> <td> :white_check_mark: </td> <td> @dbernardi </td> </tr> </table> </details> <details> <summary> ### :sparkles: Core Foundational Elements - Non-MCP Tools - Server-Side Approach </summary> <table> <tr> <th></th> <th>Description</th> <th>Sub Epic / Issues</th> <th>Status</th> <th>Technical Lead</th> </tr> <tr> <td>Create Backend Graphql For UpdateToolApproval</td> <td> * Create a graphql endpoint to handle tool approval accumulation in the DB </td> <td> https://gitlab.com/gitlab-org/gitlab/-/work_items/556045+ </td> <td> :white_check_mark: </td> <td> @dbernardi @mikolaj_wawrzyniak </td> </tr> <tr> <td>Handle serverCapabilities for backwards compatibility</td> <td> * To ensure all versions of DWS work with tool approvals, introduced passing capabilities to the client from Server/DWS </td> <td> https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/work_items/2001+ </td> <td> :white_check_mark: </td> <td> @dbernardi </td> </tr> <tr> <td>Update AI Gateway to handle tool approval</td> <td> * Ensure gateway can handle the new approved_tool_calls DB argument </td> <td> https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/issues/1874+ </td> <td> :white_check_mark: </td> <td> @dbernardi @mikolaj_wawrzyniak </td> </tr> <tr> <td>Return capabilities from DWS on direct_access token fetch</td> <td> * Without coupling LSP against a version number for DWS, now returning capabilities in token fetch to be sent to LSP through rails </td> <td> https://gitlab.com/gitlab-org/gitlab/-/work_items/592817+ </td> <td> :white_check_mark: </td> <td> @dbernardi </td> </tr> <tr> <td> \[LSP\] Extend Approve for Session option to all tool calls in DAP </td> <td> * Only MCP tool calls currently can be approved for the entire session * This will enable all tool calls to be handled by the backend server * Checks which capabilities are available from Rails/DWS before displaying Tool Approval options </td> <td> https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp/-/issues/1944+ </td> <td> :white_check_mark: </td> <td> @dbernardi </td> </tr> <tr> <td>Telemetry for Approve for Session Dropdown</td> <td> * Add telemetry feedback for existing features with the intention of continuing to add telemetry as features are created * This is the SSOT for what users are using and where the direction of the product should point next </td> <td> https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp/-/work_items/2205+ </td> <td> :white_check_mark: </td> <td> @dbernardi </td> </tr> </table> </details> ### :sparkles: Core Iterations <table> <tr> <th></th> <th>Description</th> <th>Sub Epic / Issues</th> <th>Status</th> <th>Technical Lead</th> </tr> <tr> <td>Tiered Setting for Approve Tool for Sessions (IDE + CLI)</td> <td> * Alongside having approve for session as a feature, it is consistent across customers for admin to be able to turn the feature off </td> <td> Sub-epic: https://gitlab.com/groups/gitlab-org/-/work_items/21593+ </td> <td> :white_check_mark: </td> <td> @dbernardi </td> </tr> <tr> <td>Wildcard Tool Approvals</td> <td> * In the first iteration, tool approvals rely on SHA hashes. If the tool is slightly different, the hash will be as well and tool approval will be required * This iteration allows for groups of tool calls to be approved, i.e all `npm` tools could be approved for a session </td> <td> Sub-epic: https://gitlab.com/groups/gitlab-org/-/epics/21850+ </td> <td> :construction: </td> <td> @dbernardi </td> </tr> <tr> <td>Persistent Approvals Across Sessions</td> <td> * Allow users to configure allowlists/denylists in GitLab * This will likely have two interfaces, one that caters to IDEs and one that caters to GitLab </td> <td> Sub-epic: https://gitlab.com/groups/gitlab-org/-/work_items/21877+ </td> <td> :construction: </td> <td> @dbernardi </td> </tr> <tr> <td>Autonomous Tool Calling for Session</td> <td> * Enable tool calling to always approve for all tool calls. * This effectively gives users the ability to leave DAP alone while a task is completed </td> <td> https://gitlab.com/gitlab-org/gitlab/-/issues/587061+ </td> <td> :white_circle: </td> <td> @dbernardi </td> </tr> <tr> <td>Audit Events on the Backend</td> <td> * Currently, only the client is exposing audit telemetry events about tool approvals and what type of approvals. * The two issues in this section address the audit gap that exists on the backend in both rails and DWS </td> <td> https://gitlab.com/gitlab-org/gitlab/-/work_items/603370+ https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/work_items/2407+ </td> <td> :white_circle: </td> <td>TBD</td> </tr> <tr> <td>Grouping Tools by Type/Action</td> <td> * Tools are currently grouped according to a few main groupings. However these groupings do not follow READ/WRITE/DELETE/etc groupings * Reconsider how groupings are created to allow for better tool governance </td> <td> https://gitlab.com/gitlab-org/gitlab/-/work_items/598343+ </td> <td> :white_circle: </td> <td>TBD</td> </tr> <tr> <td>Approve for Session in DAP on Web</td> <td> * As DAP on the web continues to increase it's tool usage that exists outside of GitLab's tools, it will become necessary to extend Approve for Session to this surface. * This will include the need for a UI change/review since the UI used in IDEs is unique to that surface. </td> <td> https://gitlab.com/gitlab-org/gitlab/-/work_items/596879+ </td> <td> :white_circle: </td> <td>TBD</td> </tr> </table> ### :sparkles: Documentation <table> <tr> <th></th> <th> **Description** </th> <th> **Sub Epic / Issues** </th> <th> **Status** </th> <th> **Technical Lead** </th> </tr> <tr> <td>Create Architectural Design Doc for Approve for Session</td> <td> * This tracks the architecture and decision making during creating Approve for Session in DAP. * This document lives as the SSOT for future developers to come back and reference specific decisions. </td> <td> https://gitlab.com/gitlab-com/content-sites/handbook/-/issues/591+ </td> <td> :white_check_mark: </td> <td> @dbernardi </td> </tr> <tr> <td>Create Architectural Design Doc for Tool Management/Autonomous Tool Use</td> <td> * This serves as a space for discussion between AI focused initiatives and editor extensions to safely and securely autonomy of GitLab Duo Agentic Platform </td> <td> https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp/-/work_items/2167+ </td> <td> :white_check_mark: </td> <td> @dbernardi @jeanvdw </td> </tr> <tr> <td>Create Architectural Design Doc for Security approach for tool approvals</td> <td> * This serves as the reference for developers to understand the security approach taken during development of pattern approvals/autonomous mode in the AI SDK/Raiils </td> <td>Need to create</td> <td> :white_circle: </td> <td> @dbernardi </td> </tr> </table> ### :sparkles: Cleanup <table> <tr> <th></th> <th> **Description** </th> <th> **Sub Epic / Issues** </th> <th> **Status** </th> <th> **Technical Lead** </th> </tr> <tr> <td> \[LSP\] Remove MCP specific approval code </td> <td> * To ensure backwards compatibility with new releases, the old MCP approval code still exists. * If possible, we want to consider removing this </td> <td></td> <td> :white_circle: </td> <td></td> </tr> <tr> <td>Rails: Ensure capability gate catches unknown capabilities</td> <td> * Each new capability that is added also adds a gate where if not all three surfaces have the capability the tool is not shown. * However, if an AI Gateway MR and LSP MR are merged that both pass a new capability before a rails MR merges to control that capability, the feature will display but will break the DAP chat. * This issue is to explore options for removing this concern when creating new features that are added as capabilities. </td> <td> https://gitlab.com/gitlab-org/gitlab/-/work_items/602098+ </td> <td> :white_circle: </td> <td>TBD</td> </tr> </table> ### :sparkles: Customer Zero - Dogfooding & Feature Feedback * Feedback issue: @dbernardi to create ## References * Legal approval issue: [https://gitlab.com/gitlab-com/legal-and-compliance/-/work_items/3164+](https://gitlab.com/gitlab-com/legal-and-compliance/-/work_items/3164)
epic