UX Proposal: Flow Action approvals
# User Journey: Pre-Execution Tool Approval ## Background When a flow executes in GitLab, it runs in a CI/CD runner and has access to a set of tools scoped to both the flow's configuration and the triggering user's permissions. Today, flows use those tools automatically without explicit user confirmation. --- ## Scenario Maya is a backend engineer. Her team uses a custom flow called "Triage & Draft" that analyzes newly opened issues, searches related code, and drafts a first-pass implementation plan as an issue comment. She's on the issue page for a newly filed bug. She clicks "Run with GitLab Duo" to trigger the flow. --- ## Step 1 — Tool Approval Modal The modal is titled "Review before running: Triage & Draft." A brief description of the flow appears at the top, written by the flow author: "Analyzes the issue, searches related code, and posts a draft implementation plan as a comment." Below it, tools are grouped into three permission categories. Each category can be toggled as a whole, or expanded to configure individual tools. ![image](/uploads/2616680affcdfb1401590abbae7a4b9f/image.png){width=900 height=517} ``` > Read-only tools (3) [Allow All ▾] > Write tools (3) [Allow All ▾] ``` Because no _delete_ tools are requested by this flow, that category is not shown. ![image](/uploads/13fd8aacb5410991a13a5fddbab2d085/image.png){width=900 height=528} Curious, Maya opens the Write-tools category to see what tools are included. ``` > Read-only tools (3) [Allow All ▾] v Write tools (3) [Allow All ▾] └─ ✅ create_comment └─ ✅ create_issue └─ ✅ update_issue ``` Maya notices `create_issue` is listed. She wasn't expecting the flow to create new issues — she thought it only comments. She expands the category and blocks that specific tool, leaving `create_comment` and `update_issue` allowed. ![image](/uploads/cfb0996ebe8152234d5432f979dfeaea/image.png){width=847 height=600} ``` ✅ Create / Edit [Custom] └─ create_comment ✅ Allow └─ create_issue 🚫 Block └─ update_issue ✅ Allow ``` ![image](/uploads/1add8a5ba96b7e8fa9c1b58d7d472092/image.png){width=702 height=600} A note below the tool list reads: "Blocking a tool may cause the flow to produce partial results or skip steps that depend on it." She clicks "Run Flow." --- ## Step 2 — Execution The flow begins. Maya sees the session status in the Duo sidebar: Running. She navigates away and continues her work. --- ## Step 3 — Mid-Session Approval About four minutes later, Maya receives an urgent notification: "Triage & Draft is paused — your approval is required." While analyzing the bug, the flow identified 47 open issues across two projects that share the same root cause and are now obsolete — they were filed against a deprecated API endpoint that this fix will remove entirely. The flow is ready to close them in bulk and leave a closing comment on each linking to the canonical issue. The flow author made this a hard gate: closing dozens of issues affects other engineers' work, may disrupt sprint tracking, and is tedious to reverse one by one. Maya opens the session. The runner is paused, and a prompt is waiting: ![image](/uploads/9dcee9aeab9c5d098f6c240bfca261ae/image.png){width=304 height=600} Maya approves, the runner resumes after several minutes. --- ## Step 4 — Completion From here, execution and completion behave as they do today. Maya receives a notification when the flow finishes. The session log reflects which tools were invoked, which were blocked by her pre-execution configuration, which were unavailable due to her permissions, and records her mid-session approval with a timestamp. --- ## Design Notes - **Category-level approval covers the majority of sessions.** Most users will accept the defaults or toggle a category, not configure per-tool. Per-tool configuration exists for power users and situations like Maya's. - **The tool list reflects only what this flow can request** — not every tool in the platform. The flow author's configuration is the ceiling; the user's approval is the floor. - **Blocking a tool is non-destructive.** The flow continues; it simply attempts to solve the problem but notes the tool as disabled in the session log. - **Approvals are per-session, not saved.** Each trigger is a fresh consent moment. Future iterations could allow users to save a trusted configuration for a specific flow. (Always allow this floe to run with these permissions) # Resources Figma: https://www.figma.com/design/SsVuZcbeI0RYoaGkb3BEAb/Permissions-and-Approvals---for-Frances?node-id=0-1 --- ## Alternative Approach: Policy-Driven Modal Suppression The user journey above assumes the pre-execution approval modal is always shown when a flow is triggered. This section describes an alternative behavior where the modal is suppressed entirely when group policy does not require it — reducing friction for flows that only use tools the admin has already approved. ### How it works When a user triggers a flow, GitLab evaluates whether any tool the flow requests is marked **Always ask** in the group's Tool Permissions settings (see [#591359](https://gitlab.com/gitlab-org/gitlab/-/issues/591359)). If at least one requested tool requires confirmation, the pre-execution modal is shown as described above. If no requested tools require confirmation — because all are set to **Always allow** — the flow begins immediately without presenting the modal. This means the pre-execution modal is a function of group policy, not a fixed part of the trigger interaction. Administrators control which flows surface the modal by adjusting Tool Permissions, not by configuring flows individually. ### In practice Given the proposed defaults in #591359 — Write tools set to **Always ask** and Delete tools set to **Blocked** — the modal will appear for the vast majority of flows, since most flows perform at least one write action. However, flows that are entirely read-only (using only tools in the Read-only category, which default to **Always allow**) would run immediately without interruption. An organization that wants to reduce friction further could selectively change specific Write tools to **Always allow**, removing those tools from the modal trigger calculation and allowing flows that use only those tools to run without a pre-execution approval step. ### Trade-off: users cannot restrict tools at runtime When the modal is suppressed, the user has no opportunity to review or restrict the flow's tools before execution. This is an intentional trade-off: the admin has already expressed a policy position that these tools do not require per-user confirmation. Users who want to restrict tool access for a specific run cannot do so without an admin first changing the relevant tool to **Always ask**. This trade-off is most acceptable in two scenarios: (1) flows that are entirely read-only, where there is no write or delete risk to manage, and (2) organizations with high trust in their flows and a preference for low-friction execution. ### Variant: read-only modal (no per-session configuration) A further simplification would be to remove per-session tool configuration from the modal entirely, making it informational only. In this variant, the modal shows the user which tools the flow will use, but does not allow them to block or modify individual tools. The only action available is **Run Flow** or **Cancel**. This variant reduces the complexity of the approval interaction significantly and may be more appropriate as an initial scope. In this case, suppressing the modal for all-allowed flows carries no functional loss — the user was never able to change anything anyway. The modal's value in this variant is purely transparency: confirming what the flow will do before it starts. Under this variant, mid-session approval gates set by the flow author remain unaffected. Those gates are not tied
issue