Approval model (Phase 2)
#Contract
approval.requested is written to the durable Kernel outbox before the workflow waits for a human. Its data.operation contains:
id: the stableoperation_idused by approval and subsequent tool events;type,summary;arguments: a bounded display projection with sensitive keys/values redacted;arguments_hash:sha256:plus the digest of canonical JSON for the full arguments.
data.risk is an explicit advisory level. data.redaction reports whether any fields were redacted and whether output was truncated. data.details contains only non-sensitive display metadata such as tool/workspace policy. Full canonical arguments are not copied into Temporality events.
An approval signal must provide operation_id, arguments_hash, actor_id, and decision. The workflow records approval.granted with the same operation ID/hash and starts tool.started only after an exact hash match. A mismatch is recorded as rejection and cannot execute the tool. tool.started, tool.completed/failed, and MCP lifecycle events carry the operation ID and arguments hash. All events include the same run/frame scope and causal parent links through the envelope metadata in data.
#Redaction and limits
Display data is limited to 4 KiB overall, 256 bytes per string, 32 members per collection, and six nested levels. Sensitive names include token, password, secret, authorization, credential and private key variants. Bearer values and URL user-info are redacted. Truncation and redaction are visible. The digest deliberately identifies the unredacted canonical arguments; it does not reveal them directly, though it may permit guessing low-entropy arguments.
The digest is an identity check, not proof that the UI is trustworthy or that the operation is safe. The approval UI must display the redacted operation and submit its exact hash. Tool policy and sandbox restrictions remain independent controls.
#Sandbox auto-approval
When Activities.PrepareRun confirms that the Docker sandbox is configured, it assigns the sandbox policy trio (run_command, write_file, edit_file) to the workflow's auto-approval policy and removes them from the human approval list. The deterministic workflow emits approval.auto_granted before tool.started; the event includes the bounded operation display, canonical arguments hash, workspace path, and policy_id: sandbox.workspace.v1. The sandbox still enforces its container, workspace, network, and resource settings. This policy cannot auto-approve MCP tools or the explicit request_approval tool. API callers cannot choose the policy: PrepareRun replaces the policy fields from server configuration.
The default auto-approval set: run_command, write_file, edit_file (with the sandbox configured) plus web_fetch, fetch_image (with network access), web_search (only when a SearXNG backend is configured) and browser (only when a CDP backend is configured). Everything else — MCP tools above all — asks a human unless the MCP server config exempts it (approval_tools is the require-list; anything not listed follows the default posture).
#Decision levels
Per tool call the workflow evaluates, in order: approvalRequired wins over auto-approval.
- Tool identity —
request_approvalalways asks; MCP tools listed in the server'sapproval_toolsalways ask. - Org policy —
approval_mode: toolson the effective org-unit policy forces confirmation for every consequential (non-observation) tool of every run in that scope. - Agent mode — the agent's own control level (
applyAgentConfig):monitoredkeeps the default auto-approvals but turns on the oversight judge for every completed turn;strict(and the legacyprompt,manual,tools) additionally forces confirmation for every consequential tool and zeroes the sandbox auto-approval list;autonomous(or empty; legacyauto) keeps the default posture. Set it in the agent's Parameters tab ("Tool approvals"). Org policy is applied after and cannot be loosened by the agent. - Default — otherwise the sandbox auto-approval list applies (see above).
approval.auto_granted events carry policy_id: sandbox.workspace.v1, so filtered traces show exactly what ran unattended. To audit an agent's autonomy: filter the trace by approval.auto_granted and check which tools the policy covered.
#Validation evidence
TestApprovedToolOperationIsVisibleAndHashBound checks approval.requested → approval.granted → tool.started → tool.completed, common run/frame/operation/hash, causal links, secret absence and denial when the signal hash differs. TestSandboxAutoApprovalIsRecordedAndRunsWithoutHumanSignal checks the sandbox policy event/order and verifies that it does not create a pending human request. TestApprovalOperationHashesCanonicalArgsAndRedactsDisplay checks canonical map-order stability and redaction. These are workflow-level tests; a human clicking the live UI against a real MCP write remains a separate acceptance test.