The agent is about to commit a refund, send an email, drop a database table, or push code. You want the workflow speed of an agent and the certainty that a human said yes before the irreversible part.
- Action affects users, money, infra, or external parties
- Cost of a wrong call is much higher than the cost of the agent waiting
- Compliance requires an audit trail of human approval
Refunds, account suspensions, infra changes, money movement, customer-visible communication, schema changes, force pushes, deletes.
Internal read-only operations, search, summarisation, draft generation. Approval gates kill UX when the action is reversible.
The YAML
Drop this into an app.yaml. Adjust the credential refs and module names to fit your existing setup.
1modules:2 http: {}3 context_builder: {}45execution:6 mode: conversation7 entry_agent: ops89capabilities:10 grant:11 - { module: context_builder, actions: [ask_user] }1213agents:14 - id: ops15 modules:16 - {http: [post]}17 - {context_builder: [ask_user]}18 brain: { model: claude-sonnet-4-6, credential: anthropic_main }19 system_prompt: |20 Before any irreversible POST (refunds, deletes, sends), call:21 ask_user(message="Confirm: <one-line summary>", choices=["yes", "no"])22 Only proceed when the user picks "yes". Log every decision.2324execution:25 hooks:26 - id: gate_destructive27 "on": tool_start28 condition:29 type: all_of30 conditions:31 - { type: tool_name, match: "http.post|http.delete" }32 - { type: expression, expr: "tool.params.url contains '/refund' or tool.params.url contains '/delete'" }33 action:34 type: gate35 require_approval: true36 message: "Confirm {{tool.name}} to {{tool.params.url}}"How it works
Walking through the YAML one block at a time so the design is clear, not memorised.
Two-tier safety: the prompt and the runtime
The system prompt teaches the agent to ask first. The hook enforces it: even if the agent forgets, the runtime gates destructive calls.
ask_user is a real tool, not a hack
context_builder.ask_user pauses the agent, surfaces the question on the SSE stream, and resumes when the user answers. The choice becomes a normal tool result.
Hook gate is the safety net
The gate action with require_approval routes through ApprovalQueue. The user sees a system-level prompt that survives even a misbehaving agent.
Audit trail by default
Every approval and rejection is logged with timestamps and user id. Compliance and replay both work without extra wiring.
Other ways to solve it
The pattern above is not the only answer. Here is when something else is the right call.
Plan-then-execute
Have the agent emit a plan first, the user approves the plan, then the agent executes the whole plan without per-step prompts. Less interruption, larger blast radius if approval is given to an underspecified plan.
Out-of-band review
Agent does the work, posts a draft for human review (Slack message, PR, ticket). Humans approve later. Higher throughput, weaker safety because the action is already taken.
How credentials work on Digitorn: an encrypted vault driven from YAML
Get the next post in your inbox.
Engineering notes from the Digitorn team. No marketing, no launch announcements, no "10 prompts that will change your life". Just the things we write that we'd want to read.