Approvals
Agents read and write files, run shell commands, and drive browsers. Approvals are the control surface over that — the difference between an agent you let run unattended and one you watch every keystroke of.
The policy
An ordered list of rules plus a default. The first rule that matches a tool call decides; anything uncovered falls back to the default.
extensions:
approval:
default: ask-human
rules:
- match: "bash(git log *)" # tool(pattern); first match wins
action: allow
- match: "bash(rm *)"
action: denyFour verdicts:
| Verdict | Meaning |
|---|---|
allow | Runs immediately |
deny | Refused, with a reason handed back to the agent |
ask-agent | A separate approval agent judges the call |
ask-human | Parked until you decide, in the TUI or web UI |
ask-agent is the interesting one: a second, usually cheaper model reviews the
call in context and decides. Point it at a model with the provider: key:
extensions:
approval:
provider: approval-agent
default: ask-agentApproving in practice
A parked call surfaces inline in the transcript — in the TUI, in the web UI, or
on your phone. Approve it, deny it, or deny with a comment: the comment goes
back to the agent as the reason, which usually redirects it rather than just
stopping it (“don’t use rm, move it to /tmp instead”).
Denying can also stop the turn outright when you want the agent to halt, not adapt.
Denial is a first-class outcome, not an error. An agent that gets denied is expected to route around it, and a good deny comment is the cheapest way to steer a long-running task.
Safe shell pipelines
Shell is the hard case: bash(git log *) is easy to allow, but real commands
are chains. Boba parses a shell command into its actual structure and evaluates
each stage, so a safe chain can auto-approve as a whole without you hand-listing
every permutation — and the approved command is executed as parsed arguments,
never re-parsed from a string that could mean something different the second
time.
This is opt-in. See ADR-003 for the model.
Unattended runs
Scheduled tasks and headless run-task sessions have no human to ask, so
ask-human there means “park forever”. Give unattended profiles a policy that
terminates: an explicit allow-list with default: deny, or ask-agent.
Further reading: ADR-001 covers the policy and tool-capability model in full.