Skip to main content
Approvals / AI Agents

Designing an AI agent approval workflow

Most of what an agent does should never reach a person. The workflow’s job is to let routine work run inside policy, stop the rest at a named human, and make sure the agent can never move the line between the two.

Three routes out of one decision point

Every consequential action an agent attempts passes through a single evaluation, and that evaluation has exactly three outcomes.

ALLOW
Inside policy
The action runs. Nobody is interrupted, and the decision is still recorded, because "no human was needed" is itself something a reviewer will want to see justified.
ESCALATE
Outside policy, not forbidden
Execution stops and a named human is asked for this exact action. The refusal is machine-readable (HTTP 428, carrying what to bring back), so the agent knows what would unblock it instead of retrying blind.
DENY
No approver would make it acceptable
Refused outright, with a reason. There is no signoff path, because the problem is not missing authority; it is that the action is out of bounds.

Almost every approval system has the first and the third. The value is in the middle one, and specifically in what the escalation leaves behind once the human has answered.

The load-bearing rule

The agent must never widen its own authority

A workflow that can be argued into granting itself more room is not a control, it is a suggestion. Three rules carry most of the weight here, and each of them is a refusal rather than a warning.

  • Authority only narrows on the way down. A principal that itself holds delegated authority cannot re-delegate more than it holds. A request for a scope outside what the grantor actually has is refused as a scope escalation, and the offending scope is named in the refusal.
  • Unverifiable authority is not authority. If the delegation record cannot be read, the request does not degrade to permissive. It refuses, because a store that is unreachable and a store that says no should not produce different outcomes.
  • The tier cannot be self-declared. Assurance runs software, then class_a (a device signoff), then quorum (m-of-n, the two-person rule). The action’s risk sets the floor, and a receipt that merely claims a higher tier is graded down to software and refused.

The models behind those transitions are analyzed as models, not only tested as code: 26 TLA+ invariants checked by TLC 2.19 in CI.

An approval that is a message, and an approval that is bound

When a request goes to Slack and someone clicks Approve, the artifact produced is a message: a person, at a time, approved something. It reads like authorization. Structurally it is a notification with a timestamp, and two properties separate it from an approval that can carry weight.

Bound to the exact action. The signature covers the parameters, not just the action type: the amount, the beneficiary, the repository, the record. At execution the gate compares what was authorized against what the system of record actually observes and refuses on drift. When a field is declared as required and no observed value is supplied, the check fails closed instead of passing quietly, which is the difference between a control and a formality.

Used once. Consumption is keyed to a stable, issuer-generated receipt identifier, and a second presentation of the same approval is refused as a replay. The key is deliberately not a hash of the content: canonicalization can differ between language implementations, which would silently break replay detection exactly when services written in different languages share a consumption store.

Side by side

DimensionApproval as a messageApproval bound to the action
What was approvedAn action, described in proseThe exact parameters, covered by the signature
Who approvedWhoever held the sessionA named principal, inside the signed payload
How the yes was establishedA clickAn assurance tier that had to be proven, not claimed
ReuseNothing prevents itOne-time consumption; a second presentation is refused
Drift between approval and executionUndetectedCompared against the observed action; refused on mismatch
How a third party checks itAsk the operatorVerify the signature against a pinned issuer key
What the agent can influenceThe framing it presentsNothing that sits inside the signature

Choosing what escalates

The failure mode of approval workflows is not being too strict. It is asking so often that approving becomes reflexive, at which point the human is a rubber stamp with a pager and the evidence trail records a ritual. Two heuristics keep the volume honest.

  • Escalate on irreversibility, not on size. A small payment that cannot be clawed back deserves more scrutiny than a large one that can be reversed with a phone call.
  • Escalate on the parameters that would hurt if they were wrong. Beneficiary, destination, deletion scope, blast radius. Not the name of the tool being called.

When an action is both rare and severe, raise the tier rather than the frequency. Requiring quorum on the few actions that warrant it costs the team less attention than requiring a click on everything, and it produces a stronger record for the actions that matter.

Questions

What is an AI agent approval workflow?

A single decision point in front of every consequential action an agent attempts, with three outcomes: run it because it is inside policy, escalate it to a named human because it is outside policy, or refuse it because no approver could make it acceptable. The design work is in the second outcome and in what that escalation produces.

How do you stop an agent from approving its own actions?

By making authority flow only downward and fail closed. A principal that itself holds delegated authority cannot grant more than it holds, and a request for a scope outside that is refused as a scope escalation. If the delegation record cannot be read at all, the request refuses rather than falling back to permissive. The assurance tier is also not self-declared: a receipt that merely claims a higher tier is graded down and refused.

What is the difference between an approval and an authorization receipt?

An approval is an event in your system. A receipt is a portable artifact: a signature over the exact action, the named approver, the pinned policy, and a one-time consumption key, verifiable by someone who does not trust your systems and cannot query them.

Can an approval be reused?

Not on a mediated path. Consumption is keyed to a stable issuer-generated receipt identifier, and a second presentation is refused as a replay rather than executing a second time. The key is deliberately not a hash of the content, because canonicalization differences between language implementations would silently break replay detection when services share a consumption store.

Wire it into your agent

The quickstart takes an irreversible action in MCP, LangChain, CrewAI, AutoGen, or any Node service and puts this decision point in front of it.

Open the quickstartHow enforcement works

For the record an approval leaves behind and what a reviewer does with it, see AI agent audit trails. For how this compares with a hand-rolled Slack approval, see EMILIA vs DIY human-in-the-loop.

AI Agent Approval Workflow: Escalate, Bind, Consume Once | EMILIA