Somewhere in the deployment there is a spreadsheet called something like "agent issues (temp)". It has no schema and no owner. Somebody made it in week two, because work kept arriving that the agent had not finished and there was nowhere to put it.
That spreadsheet is now the real interface between the agents and the operation. Everything else in the deployment got a design review. The place where the agent's failures land got a filename.
An agent's value is not measured only by what it completes. It is measured by how cleanly it hands off what it cannot. AI agent exception handling is the discipline of designing that handoff as an operational surface with fields, owners, and deadlines, rather than treating it as an error state engineering will look at later. The decision here is not whether to build agents. It is who owns their unfinished work by Friday, and what that person sees when they open it.
The failures you never see are the ones that cost you
Ask an operations team what happens when an agent fails and you will usually get an answer about errors. The agent threw an exception, the run stopped, someone got an alert. That is one failure class out of three. It is also the least dangerous one.
Agents fail in three distinct ways, and they route completely differently:
- Hard failures. The agent errored and stopped. An API returned 500, a credential expired, a record was locked. These are visible, they page someone, and almost every team handles them.
- Soft failures. The agent completed and the output is wrong. It mapped a field to the wrong column, filled a gap with a plausible invention, approved something at the wrong tier. Every status is green. Nothing errored.
- Abandoned work. The agent stopped partway through a batch. Sixty records processed, four hundred not, and no signal either way because nothing crashed.
Soft failures are the expensive class, and they are structurally invisible to the tooling most teams buy. Observability platforms watch for errors, latency, cost, and drift. They are very good at telling you that something broke. Some now score output quality with model-as-judge evaluation, but that produces a sampled aggregate signal on a dashboard rather than an owned work item, and per MLflow (2026) it is built to catch regressions across runs, not to route one wrong invoice to a person.
So "we have monitoring" and "we handle exceptions" are different claims. Monitoring tells you the agent is running. Exception handling tells you what happened to the work the agent could not finish correctly, and who is doing something about it right now. Most teams have the first and believe they have the second. That gap is specific, and it is fixable.
Escalation is a trigger, a queue is a destination
Almost every discussion of agent handoff answers the same question: when should the agent escalate? Confidence below a threshold. Request outside policy scope. Sentiment turning negative. Action above an authority limit. The literature here is good, and platform vendors have built it into their products. Meta Business Agent, which launched globally across WhatsApp, Instagram, and Messenger in June 2026, treats Handoff as one of four owner-configured controls, letting the business define which topics escalate to staff, and the major contact-center platforms including Zendesk (2026) and Genesys ship configurable escalation the same way.
Then the trigger fires, and the design stops.
A trigger without a designed destination is a message sent somewhere. A Slack channel. A shared inbox. A support ticket in a queue built for customer emails, or a row appended to that spreadsheet. The escalation was engineered. The thing it escalates into was not.
The vocabulary around human oversight does not help, because it measures the wrong axis. Human-in-the-loop (HITL) means a person approves or corrects individual decisions before they take effect. Human-on-the-loop (HOTL) means a person supervises outcomes and intervenes when something looks wrong . Human-out-of-the-loop (HOOTL) means full autonomy with no operational intervention. All three describe how much oversight exists. None of them describes where the work lands when oversight is required, which is the part that decides whether the oversight happens at all. (This is worth flagging in any governance review , because an oversight model can be documented in full and still have no destination attached to it.)
Design the destination and the trigger becomes a routing decision. Skip it and the trigger becomes a notification competing for attention with everything else in the channel. The rest of this article is that destination, field by field.
What an exception record has to contain
Here is the artifact almost nobody publishes: the actual contents of one exception. This is the schema that turns an alert into a work item.
| Field | Purpose |
|---|---|
| Exception ID | A stable reference an ops person can quote in a conversation or a ticket. |
| Timestamp | When the agent stopped, not when someone noticed. |
| Agent and version | Which build produced this, so behavior can be attributed to a specific change. |
| Run or trace ID | The link back to full telemetry, for the rare case an engineer is needed. |
| Task description | What the agent was trying to do, in business language. "Match invoice 4471 to a purchase order", not a function signature. |
| Stop reason | Why it could not continue, in one machine-generated line. |
| Trigger signal | What caused the handoff: a confidence score, a policy rule, an authority limit, an exhausted retry chain. |
| Inputs | What the agent was working from, so the human does not start over. |
| Partial output | What it produced before stopping, marked clearly as unverified. |
| Severity | The tier that sets the deadline and the routing. |
| Owner | A named role accountable for resolution. |
| SLA due time | An absolute timestamp, not a duration. |
| Status | Open, in progress, resolved, or reopened. |
| Resolution reason | A value from a closed list. This is the field that makes the queue analyzable. |
| Resolution note | Free text for the specifics, secondary to the coded reason. |
| Resolved by and resolved at | The audit answer to "who decided this". |
| Business reference | The customer, order, or record ID, so the work is findable from the operational side. |
One design principle governs the whole schema: an exception must be resolvable by an operations person without an engineer. If a field only means something to the team that built the agent, it belongs in telemetry, not in the queue. A stack trace is not an exception record. Neither is a JSON blob with the agent's internal state pasted into a description box.
Test it directly. Hand the record to someone on the operations team who has never seen the agent's code. Can they tell what was being attempted, what went wrong, and what a correct resolution looks like? If not, the record is not finished, and every item will end up routed to the two people who can read it. That is how a shared operational surface collapses back into an engineering bottleneck inside a month.
Severity is what makes the queue workable
Without severity, a queue is a pile. Everything in it is equally urgent, which means nothing is, and the order of work becomes whatever sits at the top of the screen.
Severity has to be anchored to business impact, not technical error class. A timeout and a validation failure can be the same technical event and completely different business events, depending on whether the affected record is a customer refund or an internal tag update. Three tiers is usually enough to start:
- Tier 1. Money moves, a customer sees it, or the action is hard to reverse. A mispriced quote that already went out. An approval above the agent's authority. A refund issued to the wrong account.
- Tier 2. Wrong output that has not yet been acted on, or work stalled inside a process with a downstream deadline. Recoverable, but expensive if it ages.
- Tier 3. Cosmetic, internal, or fully reversible. Formatting, tagging, enrichment gaps that block nothing.
Each tier carries a resolution target. Set those targets deliberately as a starting point to calibrate, not as a benchmark copied from somewhere - there is no published industry standard for agent exception handle time, and anyone quoting one is guessing. A workable first pass is same-shift for Tier 1, same-day for Tier 2, and next-review-cycle for Tier 3. Then measure what actually happens and move the numbers.
Expect the tier definitions to be wrong on the first pass. Severity is a judgment about your business, not about the agent, so nobody gets it right from a whiteboard. Build in the correction: for the first month, review every exception where the assigned tier looks wrong in hindsight, and adjust the rules rather than the individual items. Teams that skip this end up marking everything Tier 1, which is the same as having no tiers at all.
Every exception needs a named owner, not a channel
A Slack channel is not an owner. Shared visibility produces shared inaction, and the more people who can see an item the less likely any specific person is to pick it up.
Ownership means four concrete things:
- Routing by tier to a role. Tier 1 goes to the operations lead on shift. Tier 2 goes to the queue owner for that process. Tier 3 goes to the weekly review. Roles, not individuals, so the model survives someone changing jobs.
- A definition of accountable. The owner is responsible for the item reaching resolution inside its SLA. They may not do the work themselves, and that is fine, as long as the accountability does not move when the work does.
- Coverage. Out-of-hours, holidays, and absence are part of the design, not exceptions to it. An agent that runs overnight generates exceptions overnight.
- Escalation of the escalation. When an item passes its SLA, something has to happen automatically. Usually the owner's manager becomes accountable and the item's visibility increases.
There is a second-order cost here that appears in no agent business case. When the queue has no owner , the agent's failures get absorbed by whoever notices first, and that person is usually senior. They handle the rework without mentioning it, because that is faster than escalating. The problem never enters a system. The agent's reported cost stays artificially low while a well-paid person spends part of every day cleaning up after it.
The unowned queue does not eliminate the labor. It relocates it to the most expensive desk in the building and makes it invisible on the way.
Retry, or escalate?
Retry logic is where teams cause real damage, because a retry is cheap to add and its failure mode is silent.
The distinction that matters is not how many times to retry. It is what kind of failure you are looking at:
- Retry is legitimate when the condition is transient, external, and the action is idempotent. A rate limit, a timeout, a temporarily locked record, a service returning 503. Nothing about the agent's judgment is in question, and repeating the action changes nothing except the timing.
- Retry is dangerous when the failure is about judgment or state. The agent was unsure. The input was ambiguous. The action already partly happened. Repeating the attempt does not resolve the uncertainty, it produces another uncertain result, possibly a different one.
- Retry is forbidden on non-idempotent actions without an idempotency key. Payments, order submissions, message sends, anything that creates a record. This is how one flaky connection becomes three charges on a customer's card.
Two anti-patterns deserve naming. The first is unbounded retry, which turns a single failure into a cost incident and, on a metered API, an invoice nobody predicted. The second is subtler and far more common: the retry that eventually succeeds and buries the fact that the agent needed help. Attempt four worked, the run is green, and the signal that this task is systematically difficult never reaches anyone.
The rule that fixes it: every exhausted retry chain must produce an exception, and every retry that succeeds after failing should increment a counter someone reviews. A silent give-up is the worst outcome available. It produces no work item and no data. Nothing to resolve, nothing to learn from, no record that anything happened.
The audit trail is a design requirement, not a log file
Audit gets treated as a compliance abstraction, which is why it usually ends up as retention settings on a logging bucket. Reframe it as a question you have to answer under pressure.
Someone asks: who approved this decision , on what basis, and when? You have a minute. If answering requires an engineer, a query, or a log search, you do not have an audit trail. You have data from which one could in principle be reconstructed, which is a different thing and worth much less at the moment you need it.
A usable trail requires four things by design:
- Decisions recorded as events, not as state. The current status of a record tells you where it ended. An audit needs the sequence: what the agent proposed, what a human changed, what was approved, in order, immutably.
- Reasoning captured at resolution. The person closing the exception writes why while they still remember. Reasoning reconstructed three weeks later during a review is not evidence, it is recollection.
- Agent version on every record. Without it you cannot say whether a pattern of bad decisions came from a specific build, and you cannot prove that a fix worked.
- A stated retention window. Not a default that came with the logging tool. A decision, made by someone who knows what the business is obliged to keep.
For regulated contexts, the EU AI Act's Article 14 sets human-oversight requirements for high-risk AI systems, and it is the frame most compliance teams will bring to a conversation about agent autonomy. Read the provision rather than a summary of it, including anyone's summary, and translate its requirements into the specific fields your queue captures. That translation is the work. A policy document asserting that humans oversee the system proves nothing if the oversight left no record.
Resolution reasons are the only data that makes the agent better
This is the field that turns a queue from a cost center into an instrument, and the one almost every implementation gets wrong by making it free text.
A free-text resolution note is unanalyzable. Two hundred notes describing the same underlying problem in two hundred phrasings cannot be counted, and what cannot be counted cannot drive a decision. A closed list of resolution reasons turns every resolved exception into a data point.
A starter taxonomy, which you should expect to revise:
- Agent lacked data. The information needed was not available to it.
- Agent lacked permission. It could have decided correctly but was not authorized to act.
- Instructions ambiguous. The task specification allowed more than one defensible reading.
- Edge case out of scope. Legitimately outside what the agent was designed to handle.
- Upstream data wrong. The agent behaved correctly on bad input.
- Agent reasoning error. It had what it needed and got it wrong.
- Correct escalation by policy. It should have escalated, and it did.
- False escalation. It escalated something it could have handled.
The value is in what a rising count tells you to do, and that mapping is the part rarely written down:
- Rising instructions ambiguous is a specification problem. Fix the prompt or the task definition.
- Rising false escalation is a threshold problem. Your confidence bar is too conservative and you are paying humans to do work the agent already handles.
- Rising upstream data wrong is not an agent problem at all. It is a data-quality problem the agent surfaced, and no amount of agent work will fix it.
- Rising agent reasoning error is the one that should stop a scope expansion.
- Rising correct escalation by policy with stable volume is what a healthy agent looks like. It is not a defect.
That last line is the one worth arguing about with your own team. Without a coded reason, every exception reads as a failure. With one, you can separate an agent that is breaking from an agent that is correctly declining work it should never have been handed. Those two situations call for opposite responses. One needs fixing. The other needs a wider mandate.
The learning loop that closes the gap
Everyone writing about human oversight asserts that human corrections improve the system. Almost nobody specifies the mechanism, which is why the loop usually does not exist.
Make it boring and scheduled:
- A cadence. Weekly while the agent is new, monthly once it stabilizes. On the calendar, with the same status as any other operational review.
- A named reviewer. Someone who can authorize a change to the agent, not just observe the data.
- An agenda that is the resolution-reason counts. Not anecdotes about the worst exception of the week. Counts, trends, and the tier distribution.
- A required output. Each cycle produces at least one concrete change: a prompt revision, a scope adjustment, a threshold move, an upstream data fix, or a documented decision to accept a category of exception as permanent.
Two counter-metrics keep the loop honest. Track exception rate as a share of total volume, and track escalation appropriateness separately as the share of escalations that were correct. Optimizing the first alone has an obvious cheat: raise the autonomy threshold, escalate less, and watch the number improve while soft failures increase. Watching both makes that trade visible. (Most teams discover the cheat by accident, usually in the second month, when a rate improves for no reason anyone can explain.)
Which leads to the inversion this whole design is built toward. A well-run exception queue is not evidence that your agent is failing. It is the instrument that tells you where its limits currently sit, which is the only honest basis for deciding to widen them . Teams with no queue cannot expand agent scope safely, because they have no data about the boundary. Teams with a good one can point at the resolution-reason distribution and say precisely which category of work the agent is now ready to own.
The queue is how an agent earns more autonomy.
Design the queue before you widen the scope
Most of the work described here is design work, not engineering. The schema, the severity tiers, the ownership map, and the resolution taxonomy are decisions about how your operation runs, and they are cheaper to make before the agent is carrying volume than after.
Discovery Sprint - a one-week engagement that produces the exception queue design, severity model, and ownership map for the agents you are already running, as specifications your team can implement rather than a slide deck.
Key takeaways
- Agents fail in three ways, and the expensive class is the one that completes with wrong output. Observability tooling is built to catch errors, so this class passes straight through it.
- Escalation triggers are well understood and widely implemented. The destination those triggers route into is almost never designed, which is where the failure actually happens.
- An exception record needs around seventeen fields and one governing rule: an operations person must be able to resolve it without an engineer.
- Severity should be defined by business impact, never by technical error class, and every tier needs a named owner rather than a shared channel.
- Retry is for transient external conditions. Retrying a judgment failure produces another judgment failure, and a retry that eventually succeeds hides the fact that the agent needed help.
- Resolution reasons must come from a closed list. Free text cannot be counted, and uncounted exceptions cannot improve the agent.
- A queue with a review cadence is what lets you widen an agent's scope on evidence instead of optimism.