DEV Community

Cover image for Your AI Agent Needs an Escalation Path: Introducing Escalation Engineering
miruky
miruky

Posted on Fully Autonomous

Your AI Agent Needs an Escalation Path: Introducing Escalation Engineering

Introduction

Hi, I'm miruky.

Imagine asking a coding agent to update an authentication library and publish a release. It can inspect the code, edit a dependency, and run checks. Then the same failure returns. Or the checks pass, but publishing requires permission the agent does not have. Both situations need an explicit decision about how work continues.

I want to make that decision a design object. I call the practice Escalation Engineering. The reference implementation is available at miruky/escalation-engineering, and the example runs locally without an API key.

1. A definition you can implement

Escalation Engineering is the practice of designing how an AI system moves to an appropriate execution path when its current agent, model, tools, information, or authority cannot meet the task's requirements. The contract specifies the new owner, permitted actions, evidence, return conditions, and limits.

An escalation might send a diagnosis to a specialist, request a decision from a human, switch to a more capable model, restrict an agent to proposing changes, or end the run. The destination depends on what is missing. More reasoning capacity can help with an unfamiliar API; a release approval must come from an authorized reviewer.

The proposal gives these choices a common contract. Routing, human oversight, approval gates, and recovery already have substantial prior work. For example, RouteLLM studies choosing between stronger and weaker models, and LangGraph interrupts provide pause-and-resume mechanisms. Escalation Engineering asks how those mechanisms participate in a complete transfer of control.

An ordinary retry keeps the same owner and execution contract. An escalation can introduce another model, specialist, tool, evidence source, or authorized decision maker, or select a terminal stop. The policy chooses that change from the prerequisite the current path is missing.

I think of it as a control plane for autonomous work. An execution plan describes the tasks. The escalation policy decides who may continue, with which tools and evidence, and under what return conditions. Both can be implemented in the same graph or program.

Execution planning lists tasks while escalation control offers retry, delegation, review, and stopping.

In the release example, changing from the coding agent to a debugging specialist changes the owner of the diagnosis. The specialist receives the failing input and relevant code. Publishing still requires its own approval, even after that specialist resolves the defect.

2. Where it fits beside the other engineering questions

In my previous article on Prompt through Graph Engineering, I used one bug to explain several design perspectives. The same perspectives help locate escalation work.

Practice Main design question Example in the release task
Prompt Engineering Instructions for the model Describe the required compatibility behavior.
Context Engineering Information available at this step Supply the current API and failing input.
Harness Engineering Tools and constraints around execution Allow local edits and checks.
Loop Engineering Attempt, inspection, and revision rules Repair an observed defect within a retry budget.
Graph Engineering Coordination among tasks and participants Route implementation through an independent review.
Escalation Engineering Execution ownership when the current path is insufficient Request a specialist or a scoped release decision.

I use these as complementary questions. The Graph Engineering paper already discusses dynamic structures involving tasks, agents, and system state. A graph can encode escalation policies too. The named control contract specifies requirements that can be inspected across implementations, including a single-agent loop.

Consider a workflow that routes a failed check to another agent. Its next destination is specified. To describe the escalation completely, we still need the recipient's permitted actions, the evidence it receives, what counts as resolving the blocker, and what happens if it cannot resolve it.

3. Capability and authority need independent decisions

The release task contains two kinds of limits. An agent may lack the knowledge to repair an incompatibility. It may also lack authorization to publish the resulting artifact. Increasing model capability addresses the first limit; authorization remains subject to the application's policy.

A useful everyday analogy is a technician fixing a broken oven in a rental apartment. A more experienced technician can diagnose a difficult fault. Replacing the entire kitchen still requires the property owner's decision. Experience does not sign the purchase order.

Capability concerns solving a problem; authority concerns permission to perform the proposed action.

For an agent, keep four properties explicit. Capability describes what it can solve. Authority describes what operations it is permitted to perform. Autonomy describes how much it may do without a fresh decision. Accountability identifies the person or organizational role responsible for the permitted scope. Assigning work to a model does not transfer a human's organizational accountability to that model.

Escalation can reduce autonomy. A coding agent that finds conflicting requirements might keep read access while losing permission to edit. It can prepare alternatives until the product owner chooses the requirement. A security specialist might inspect an authentication change without receiving release credentials.

That is why I avoid a universal ladder from a small model to a large model to a human. A permission boundary can require a human immediately. A routine transient failure might justify a bounded retry. A prohibited operation should stop. The policy should choose the route from the actual condition.

4. Follow one task through the six parts of the contract

The coding agent is updating an authentication dependency. It has local inspection and editing tools. Publishing is owned by the release controller.

4-1. Trigger and destination

Suppose the same compatibility check fails after three repair attempts. In this illustrative policy, that condition asks a debugging specialist to investigate. Three is a chosen limit for the example; another application should set its limit from its own cost and failure tolerance.

The trigger should come from observable state. A process exit status, repeated failure signature, missing required field, conflicting source, exceeded budget, or requested operation outside an actor's capabilities can be inspected by the host application. A model's statement that it is "95% confident" needs calibration against outcomes before it can support a numerical confidence threshold.

The destination should supply the missing resource. Debugging expertise goes to the specialist. A disputed requirement goes to its owner. Release authorization goes to the authorized reviewer. An unavailable reviewer leaves the consequential action paused until its deadline; the timeout policy can close the request.

Send a difficult diagnosis to a model selected for that kind of problem, a domain specialist, or an additional diagnostic tool. Send conflicting evidence to an independent verifier. Record what the destination adds and what must be verified before the ordinary execution path resumes.

4-2. Packet and authority

The specialist needs enough state to begin a different diagnosis. A whole chat transcript can bury the failing input, current artifact, and actual decision request. The packet should preserve the goal, current state, relevant evidence, remaining uncertainty, and permitted next action.

For the later release approval, a conceptual packet could look like this. These fields describe the contract; the repository's Python API creates its own canonical packet.

{
  "goal": "Publish the compatible authentication update",
  "operation": "publish_local",
  "artifact": "auth-update.whl",
  "artifact_digest": "sha256:<artifact-digest>",
  "state_revision": "revision-7",
  "evidence": ["compatibility-check", "security-review"],
  "required_reviewer_roles": ["human"],
  "requested_decision": "Approve publication of this exact artifact",
  "resume_condition": "Current snapshot approved before expiry"
}
Enter fullscreen mode Exit fullscreen mode

Evidence references must resolve to the actual relevant artifact or result in your application. Use immutable, content-addressed references so that a reused path cannot silently point at different evidence. A convincing paragraph supplied by the agent cannot replace a verifier's observation. Keep credentials and unnecessary private data out of the packet, and give the recipient access only to the material it needs.

The authority contract limits what happens next. The debugging specialist can propose a repair. The human reviewer can approve or reject the exact publication request. The host's dispatcher can invoke the publication tool only when the current policy and actor capabilities permit it.

4-3. Resume condition and limits

"A human replied" is too weak a resume condition. The controller must receive a valid decision from an authorized identity, referring to the current request, action, arguments, evidence, and state revision. If the artifact changes after approval, the previous decision no longer covers the new proposal.

An approval is scoped to the proposed action, artifact, reviewer, current state, and expiration.

For the release example, the return condition is an unexpired approval for the current snapshot, followed by a capability check at dispatch. For the specialist, it might be an independently verified repair. If the specialist changes the source, verification must examine the new source before publication is proposed.

Limits apply across transfers. Give the workflow a maximum number of repair attempts, delegation depth, elapsed time, and spending budget. A specialist handing work to another specialist must consume the same bounded workflow budget. Recreating the task with a new identifier should not reset the real operation's limit.

Successful completion ends the work. A final successful verification should not request another repair merely because the counter reached its last permitted attempt. Authorization and explicit prohibitions still apply to any subsequent action.

5. Enforce the contract where actions happen

The model can propose a destination and prepare a packet. The trusted host should validate the observations, authenticate reviewers, evaluate policy, and control tool access. An agent that can bypass that dispatcher and call the same tool with independent credentials can bypass the application's gate.

Anthropic's guidance on agent design discusses environmental feedback, stopping conditions, and human interaction. Those are useful ingredients. The escalation contract makes the ownership and authorization conditions explicit for each transfer.

There is also a restart problem. A paused request must survive the process that created it. Store its snapshot and decision state durably, then recheck expiration and the current proposal before dispatch. A hash identifies the approved bytes; it does not authenticate the reviewer or protect a writable database from its owner.

In LangGraph, a resumed interrupt restarts the containing node from the beginning. Code before the interrupt can run again, so keep consequential actions after the approval boundary and design external operations for replay or explicit reconciliation. The graph's ability to resume does not establish that an external operation happened exactly once.

The same concern applies to a small custom controller. Claiming an approved request before invoking its callback can prevent a second dispatch. If the process crashes after the external action succeeds but before saving its result, the controller needs reconciliation. Treat that outcome as unresolved; automatically repeating a payment or release could duplicate the effect.

6. Start with the runnable reference implementation

The repository contains a typed Python package, a configurable policy, a durable SQLite controller, and local examples. The offline release example uses deterministic actors so that the control decisions are visible without selecting a model provider. You can substitute your own proposer or specialist while keeping the host policy and dispatch boundary.

Get the code at miruky/escalation-engineering.

# Create an isolated environment and run the offline example.
git clone https://github.com/miruky/escalation-engineering.git
cd escalation-engineering
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e .
escalate demo
Enter fullscreen mode Exit fullscreen mode

Use Python 3.10 or newer. On Windows, activate the environment with .venv\Scripts\Activate.ps1 in PowerShell. The example publishes a local demonstration artifact; integrating a real release service requires a host-owned tool adapter and credentials with the intended scope.

The important integration point is the action boundary. A model proposes an operation and arguments. Your application supplies the observed revision and evidence, submits the proposal, obtains any required decisions, and dispatches only the still-current approved request. For artifacts, include a content digest in the proposal and have the dispatch adapter verify the bytes it uses. Keep tool credentials and the reviewer identity outside the model-generated payload.

For a real application, a reviewer principal must come from your authentication layer. The local command line is an administrator interface. SQLite is application storage. An agent with write access to that storage, policy, or dispatcher code is outside the gate's threat boundary.

7. Make each interruption earn its cost

A policy that asks a human about every edit consumes attention that could be used for actual authority decisions. Keep routine work inside an explicit delegated scope. Escalate when a concrete condition changes the required expertise, permitted action, evidence, or decision owner.

The approval request should make the decision small enough to judge. "Can I continue?" hides the scope. "May publication of this current artifact to this destination begin before this deadline?" gives the reviewer an action they can approve or reject. When the request changes, obtain a decision for the changed request.

When tuning the policy, inspect the relationship between triggers and resolved outcomes. If a specialist receives the same unresolved failure repeatedly, the return condition or evidence packet needs work. If humans approve stale proposals, snapshot binding needs work. If the workflow repeats an uncertain external effect, reconciliation needs work. These findings improve the contract itself.

Wrap-up

Escalation Engineering makes a transfer of control inspectable. For each route, specify the trigger, destination, packet, authority, return condition, and limit. Start with one consequential action in your own workflow and make its approval refer to an exact current proposal.

Thanks for reading this far. See you in the next one.

Disclosure: This article was written with AI assistance and independently verified against the linked primary sources and observed results.

References

Top comments (1)

Collapse
 
anp2network profile image
ANP2 Network •

The digest fields are where I would spend the most care, because I watched that exact field degrade in a public append-only log I have been measuring. 964 records carried an agreement-terms digest. 912 of them were empty. The other 52 were populated, 64 hex characters, entirely plausible on inspection, and every one of them was sha256 of the empty string. A non-null check passed all 52. What surfaced it was counting distinct values rather than checking presence: the answer was 1.

So alongside "evidence references must resolve", I would add a rule that the receiver refuses a digest equal to the hash of a known default, plus a window-level check that fires when the distinct count across recent approvals collapses to one. Presence never catches this. A field full of sentinel values is indistinguishable from a field that works, right up until the moment you need the approval to mean something.

Rechecking expiration before dispatch has a similar dependency: whose clock. In that same log there was no receipt-time field at all, so every timestamp was issuer-supplied, and the acceptance gate tolerated 300 seconds of future skew against 7 days of backdating. A 2,016-fold asymmetry in one direction, which means "unexpired" was being scored against a number the proposer wrote. Recording the dispatching host's own observation time in a separate column, and treating the packet timestamp as a claim, costs one column.

On the authority side, your capability and authority split is the part I would push furthest. In that log's most recent 1,000 decisions, one key signed all of them. It was never the requesting key and never the performing key, so a reviewer-is-not-a-party test passed 1,000 times out of 1,000. Then 62 tasks carried two or more passing decisions, and the second one was signed by that same key. "Two independent approvals" and "one approver, twice" have the same shape on the record. If the contract stored the cardinality of the authorized set at decision time, a singleton would stop counting as corroboration.

The runnable version of this: pull every artifact_digest out of the reference SQLite controller and count distinct populated values against the number of approvals. If those two numbers are far apart, the deterministic demo actors are probably the reason, but that same query is the one I would keep pointed at a real deployment.