Documentsagenta
Tool Permission System
Tool Permission System
Type
Topic
Status
Published
Created
Jul 7, 2026
Updated
Jul 7, 2026

Tool Permission System (Allow / Ask / Deny)#

Gateway tools in agenta support an explicit three-level permission model: allow, ask, and deny. Permissions operate at two scopes:

  • Per-tool: each tool carries a permission field (allow | ask | deny | inherit).
  • Per-agent default: runner.permissions.default with four modes: allow, ask, deny, and allow_reads (the default — reads auto-approve, writes trigger human approval).

The model was introduced in PR #4811 and redesigned in PR #5041, replacing the previous fragile session-id-based approach (permissionPolicy, needsApproval) with a single authored-to-enforced contract. The UI surface for canonical gateway tools was standardized in PR #5140.

Key rule: inherit (or unset) falls back to runner.permissions.default; an explicit tool-level value always wins.

Permission Values & Wire Format#

ScopeValues
Per-toolallow · ask · deny · inherit
Agent defaultallow · ask · deny · allow_reads (default)

Semantics :

  • allow — tool executes without human intervention.
  • ask — runner pauses; a pending_interaction event fires; the frontend renders Approve/Deny buttons.
  • deny — tool is rejected immediately.
  • allow_reads (agent-level only) — read operations execute; write operations escalate to ask.

Wire format — the run request carries:

{ "permissions": { "default": "allow_reads", "rules": [...] } }

The legacy permissionPolicy and needsApproval fields are removed (old drafts with these keys are silently ignored) .

UI Components (Agent Template Interface)#

All frontend components live under web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/.

ToolItemControl.tsx — the per-tool permission select rendered in the agent template. Exposes the four values (allow, ask, deny, inherit). Introduced in PR #4811.

ToolFormView.tsx / FunctionToolForm — the drill-in form for an individual tool. In PR #5140, the legacy rendering body was extracted into an inner FunctionToolForm component; canonical gateway tools now route through a CanonicalGatewayToolForm wrapper that fetches catalog details via useToolActionDetail(integration, action), synthesizes the equivalent legacy function shape for display, and delegates to FunctionToolForm. The on-disk draft is never mutated — the synthesized shape is display-only .

toolUtils.ts — exports parseGatewayTool(tool) (normalizes both canonical type:"gateway" objects and legacy slug-encoded function tools into a shared ParsedGatewayTool view) and gatewayToolIdentity(view) (stable identity = provider + integration + action + connection; permission is excluded from identity because it is policy, not identity) .

AgentTemplateControl.tsx — uses selectedGatewayIds (a set of identity strings) and removeGatewayToolByIdentity() to track and remove gateway tools by encoding-independent identity, supporting both canonical and legacy tools uniformly .

Fail-safe: if useToolActionDetail cannot resolve the action, the drill-in renders a warning plus a read-only JSON view instead of crashing .

Enforcement & HITL Flow#

services/runner/src/permission-plan.ts is the single decision module that enforces permissions for both the Pi relay gate and the Claude Code gate . Both gates read from the same parsed permission plan so they cannot disagree.

When a tool is gated with ask:

  1. The runner pauses execution and emits a pending_interaction: {id, tool} in the batch response envelope.
  2. The frontend shows Approve/Deny buttons immediately (not held by conversation busy state) .
  3. Approval decisions are keyed on stable anchors: tool spec name (relay) or recorded tool_call name (Claude gate) plus canonical args hash .
  4. Each decision is consumed once; a config change to deny overrides a stale approval.

For Claude Code gateway tools, the runner generates .claude/settings.json with per-tool MCP rules using the naming convention mcp__agenta-tools__<tool_name>. An allow permission bypasses Claude's own gate; ask preserves HITL .

Playground Support (Roadmap)#

The Agent Template interface has full permission support. The Playground is partially behind:

  • The ToolSelectorPopover, PromptSchemaControl, and ToolItemControl components in the Playground still key off the legacy slug encoding and do not yet handle canonical type:"gateway" objects .
  • PR #5140 is explicitly read-path only — both encodings are already equivalent server-side, but the Playground edit path still writes the legacy shape on add and convergence to canonical is deferred .
  • The commitDiff layer keys tools by function.name, so canonical tools get positional (not identity-based) change-diff tracking until this is addressed.

The follow-up work is to update these Playground components to read through parseGatewayTool and the identity utilities from toolUtils.ts, mirroring what Agent Template already does.

Tool Permission System | Dosu