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.
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 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
| Dimension | Approval as a message | Approval bound to the action |
|---|---|---|
| What was approved | An action, described in prose | The exact parameters, covered by the signature |
| Who approved | Whoever held the session | A named principal, inside the signed payload |
| How the yes was established | A click | An assurance tier that had to be proven, not claimed |
| Reuse | Nothing prevents it | One-time consumption; a second presentation is refused |
| Drift between approval and execution | Undetected | Compared against the observed action; refused on mismatch |
| How a third party checks it | Ask the operator | Verify the signature against a pinned issuer key |
| What the agent can influence | The framing it presents | Nothing 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.
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.