Escalations
Some calls should not be a yes or a no decided in advance. An agent searching the web is usually fine; an agent searching the web on a machine you share is a decision you want to make when it happens. Escalation is the third answer — pause, ask, continue.

The agent is suspended mid-call. Nothing has run yet, and nothing will until you answer.
Three outcomes
| What happens | |
|---|---|
| allow once | This call proceeds. The next identical call asks again. |
| allow always | This call proceeds, and a grant is written so it stops asking. |
| deny | The call is refused. The agent is told, and carries on. |
Escape denies. A policy prompt has no neutral exit — the call is blocked on your answer
either way, so dismissing it would just mean waiting for a timeout to deny it for you.
Denial is not a crash. It reaches the agent as an ordinary error naming what was refused, and a well-written agent adapts:

Where the rule comes from
Two files can ask for a prompt, and they answer different questions.
axon.config.ts — what this agent needs. The author knows their agent pushes to git
and wants a human on it:
// my-agent/axon.config.ts
export default defineAgent({
policy: {
process: { allow: ["git *"], escalate: ["git push*"] },
},
})
profile.config.ts — what you allow on this machine, across every agent, including
ones you installed and never read:
// profile.config.ts
export default defineProfile({
policy: {
tools: { search: "escalate" },
process: { run: "escalate", spawn: false },
},
})
The profile is a ceiling. An agent can narrow within it and can never widen past it, so
search: "escalate" above means every agent asks — whatever its own config says. The
stricter of the two layers wins on every call.
That is the division worth internalising: the agent's config is a statement about the
agent, the profile's is a statement about your machine. "This agent only reads ./src"
belongs to the author. "Nothing on my laptop touches ~/.ssh" belongs to you, because it
cannot depend on every agent author agreeing with you forever.
See policy and profile policy for the full field reference.
What "allow always" actually writes
A grant — recorded in your profile, not in either config file.
That placement is deliberate. Editing a config you authored from a palette keypress is invasive, and an agent-level grant could not widen a profile that escalated anyway, so "always" would fail confusingly in exactly the case that produced the prompt.
A grant is keyed to the agent and the exact subject you were asked about, never widened
into a pattern. Approving git push origin main does not silently become git push * —
if you want that, write it in your config, where it is a decision you made rather than one
inferred from a single yes.
A grant can only ever satisfy an escalation. It can never overturn a deny from either
layer. "Stop asking me this" and "override the rule I set" are different acts, and
collapsing them would let one keypress undo a machine-wide rule you set deliberately.
Grants live in ~/.axon/profiles/<you>/store/grants.jsonl, and revocation appends rather
than rewrites — a decision made and later withdrawn is two facts, not zero. The file is the
audit trail.
More than one at a time
Escalations queue. Two overlapping wakes can both raise one, and neither may be dropped: a dropped escalation is a denial you never saw, on a call you might well have allowed.
They are answered oldest first — the agent blocked longest is the one closest to timing out inside its capsule. And a request's clock starts when it is shown to you, not when it was raised, so the ones waiting behind the current prompt are not burning their deadline while you read.
When nobody is watching
Headless — axon run, cron, CI, a route handler — there is no surface to ask. Escalations
fail closed after the capsule's timeout, 30 seconds by default and configurable via
resources.escalationTimeoutMs.
They are recorded as expired rather than denied, which is a real distinction: nothing refused the call, nobody was there. The record survives, so approving the request later writes a grant that the next attempt reads.
The practical consequence: an agent you intend to run unattended should not depend on escalation. Decide those rules in config, where they hold with nobody present.
Seeing what happened
Every escalation is recorded — including ones you answered instantly — which is what makes "three escalations this session, two approved" answerable after the fact.
In a conversation the decision shows inline: capsule:escalating while it waits,
capsule:denied if refused. :open log puts the full event stream in your editor, and
:open flame shows where the pause sat in the run. See
events.
See also
policy — the agent's own block, and every rule shape.
profile policy — the machine-wide ceiling.
Kernel & Policy — how enforcement works, and why a denied call never reaches the function body.