Permission modes & approvals

The permission system answers one question: may this tool call run, or must a human be asked first? It has three layers — the mode (what the user selected), project rules (WorkApprovalRules) and tool risk (read / write). Rules always outrank the mode.

The five modes

ModeBehaviourTypical use
planNon-read-only tools are refused outright (not "ask then run"), with a fixed refusal messageLet the model design, touch nothing
readonlyRead-only tools allowed, write tools refusedReading code, researching, analysis
ask (default)Each write operation asks for approvalFirst pass in an unfamiliar repository
autoRoutine writes run directly; sensitive operations still askTrusted, repetitive work
bypassEverything allowed except what rules explicitly denyOne-off tasks in disposable environments

Invalid values fall back to ask (with legacy read-only / read_only accepted).

Decision order

  1. Mode hard limits: plan / readonly are evaluated first and short-circuit — project rules cannot loosen them.
  2. Project rules: match WorkApprovalRule by tool name and path; deny overrides any mode, and allow also lets calls through under ask / auto.
  3. Mode + tool risk: with no rule matched, read-only tools follow the mode, write tools resolve to "execute" or "request approval".

Rule model

FieldDetails
ToolNameTool name, * wildcard supported
PathPatternOptional path match; only file tools participate (read/write/delete/move/apply-patch)
Decisionallow or deny; anything else fails on create
IsEnabledRules can be disabled without deleting them

Match scoring: an exact tool name beats a wildcard, and a rule with a path beats one without. Duplicate rules for the same tool and path pattern are merged on create to avoid rule churn.

How run modes interact

  • interactive: keeps the selected mode and confirms step by step.
  • autopilot: promotes ask to auto (fewer interruptions) but never promotes plan / readonly — hard limits are not bypassed by unattended runs.

Differences across the three entry points

EntryPermission source
Code sessionsAll three layers: mode + project rules + tool risk; PermissionMode and AgentMode persist on the session
Chat pageMode + per-tool overrides (ToolApprovalOverrides); project rules are not read — chat has no project context
Workflow nodesNode-level toolApprovals plus the run-level toolApprovalMode, the latter only filling tools without an explicit setting

Approval round trip

  1. When the decider returns "needs approval", the loop emits an approval_request event (tool name and arguments).
  2. The UI renders an approval card: approve or reject, optionally with a reason.
  3. Approval executes that single call and feeds the result back; rejection returns the reason as the tool result so the model can choose another approach.
  4. Not to be confused with question: approval_request asks "may I run this tool", question asks the user for information. They carry separate ids.

Safety advice

  • Start unfamiliar repositories in ask, then switch to auto once the tool surface matches expectations.
  • Write deny rules for tools that must never run unattended (deleting files, pushing code) — those hold even under auto / bypass.
  • Use path rules to scope access, e.g. allow writes under docs/** while the rest still asks.
  • MCP tools share the same decision path; run a new server in ask once to see what it actually calls.

Observability and troubleshooting

  • The rule API returns WorkApprovalRuleDto; an invalid decision reports approvalRule.invalidDecision, a missing rule approvalRule.notFound.
  • A rejected tool call appears in the message stream as a tool result with the reason — that is why the model "did not do that thing".
  • If a call was allowed or blocked unexpectedly, check project rules first (they outrank the mode), then whether the run mode promoted ask to auto.