Coco

Escalations

A verdict that a person has to answer, how it reaches them, and where their answer is recorded.

Escalations

An ESCALATE is the gate saying a person has to decide this one. The agent waits. It cannot approve itself, and silence is not a yes.

How it reaches someone

In Claude Code an escalation is a permission prompt, in the session, at the moment it happens. Answering there is the fast path.

  ● Read(.env)
    Coco: The agent is reading a file that holds a credential
    Approve?  y/n

On the SDK road the verdict comes back as ESCALATE and your harness decides where it goes. Park the action, put it in front of whoever holds the decision, and do not let the agent proceed while it waits.

verdict = gate.check("payment.send", payload)
if verdict.escalated:
    park_for_a_person(verdict.reason)

The person answers on the dashboard, where the escalation queue shows what the agent wanted, the rule that paused it and the reason, and their decision is written next to the receipt. Resuming the parked action afterwards is your harness's job, because the gate authorises calls and does not schedule them. There is no webhook that pushes a decision back to your harness today, so a harness that needs to resume automatically polls the receipt it parked on, and saying otherwise would be wrong.

Working the queue

Everything held is also in the ledger.

coco escalations
1 waiting on a decision

  #2  2026-08-24T05:57:45Z  Read
     rule    baseline.credential_access/credential_read_needs_a_person
     reason  The agent is reading a file that holds a credential
     action  /tmp/.env
     coco approve 2 | coco deny 2

Each item shows what the agent wanted to do, the contract that paused it, and the reason in a sentence.

coco approve 41 --comment "second pair confirmed with the customer"
coco deny 42 --comment "no mandate line covers this"

The decision is written next to the receipt it answers, so the record shows what was held, who released it and why. Write the comment for the person reading the record in a year.

A receipt that already carries a decision keeps it. A second approve on the same id is refused rather than silently overwriting the first, because an audit trail where a decision can be replaced is not an audit trail.

When an escalation cannot reach anyone

A permission mode that never prompts has nobody to ask. The gate converts the escalation itself rather than relying on the runtime, so the receipt says what actually happened.

This needed an operator decision and permission mode 'bypassPermissions'
does not prompt, so it was denied instead

Which way it goes is escalate_fallback in your mandate, and deny is the only answer that keeps an escalation meaningful.

Choosing escalate over block

Reach for ESCALATE when a person legitimately can approve the action and there is somebody to ask. Reach for BLOCK when nobody inside this mandate should be able to.

The trap is escalating everything. A queue nobody works is a queue that trains people to approve without reading, and at that point the escalation is a slower allow. If a rule escalates constantly on ordinary work, the rule is drafted wrong.

Next

On this page