showcase/shell-docs/src/content/ag-ui/drafts/interrupts.mdx
Agents often need to pause execution to request human approval, gather additional input, or confirm potentially risky actions. Currently, there's no standardized way to handle these interruptions across different agent frameworks.
Support human-in-the-loop pauses (and related mechanisms) natively in AG-UI and CopilotKit. This enables compatibility with various framework interrupts, workflow suspend/resume, and other framework-specific pause mechanisms.
This proposal introduces a standardized interrupt/resume pattern:
sequenceDiagram
participant Agent
participant Client as Client App
Agent-->>Client: RUN_FINISHED { outcome: "interrupt", interrupt:{ id, reason, payload }}
Client-->>Agent: RunAgentInput.resume { threadId, interruptId, payload }
Agent-->>Client: RUN_FINISHED { outcome: "success", result }
type RunFinishedOutcome = "success" | "interrupt";
type RunFinished = {
type: "RUN_FINISHED";
// ... existing fields
outcome?: RunFinishedOutcome; // optional for back-compat (see rules below)
// Present when outcome === "success" (or when outcome omitted and interrupt is absent)
result?: any;
// Present when outcome === "interrupt" (or when outcome omitted and interrupt is present)
interrupt?: {
id?: string; // id can be set when needed
reason?: string; // e.g. "human_approval" | "upload_required" | "policy_hold"
payload?: any; // arbitrary JSON for UI (forms, proposals, diffs, etc.)
};
};
When a run finishes with outcome == "interrupt", the agent indicates that on
the next run, a value needs to be provided to continue.
type RunAgentInput = {
// ... existing fields
// NEW: resume channel for continuing a suspension
resume?: {
interruptId?: string; // echo back if one was provided
payload?: any; // arbitrary JSON: approvals, edits, files-as-refs, etc.
};
};
threadIdinterrupt, the interruptId must be provided via
RunAgentInputAgent sends interrupt:
{
"type": "RUN_FINISHED",
"threadId": "t1",
"runId": "r1",
"outcome": "interrupt",
"interrupt": {
"id": "int-abc123",
"reason": "human_approval",
"payload": {
"proposal": {
"tool": "sendEmail",
"args": { "to": "[email protected]", "subject": "Hi", "body": "…" }
}
}
}
}
User responds:
{
"threadId": "t1",
"runId": "r2",
"resume": {
"interruptId": "int-abc123",
"payload": { "approved": true }
}
}
Agent requests approval with context:
{
"type": "RUN_FINISHED",
"threadId": "thread-456",
"runId": "run-789",
"outcome": "interrupt",
"interrupt": {
"id": "approval-001",
"reason": "database_modification",
"payload": {
"action": "DELETE",
"table": "users",
"affectedRows": 42,
"query": "DELETE FROM users WHERE last_login < '2023-01-01'",
"rollbackPlan": "Restore from backup snapshot-2025-01-23",
"riskLevel": "high"
}
}
}
User approves with modifications:
{
"threadId": "thread-456",
"runId": "run-790",
"resume": {
"interruptId": "approval-001",
"payload": {
"approved": true,
"modifications": {
"batchSize": 10,
"dryRun": true
}
}
}
}
Agents pause before executing sensitive operations (sending emails, making purchases, deleting data).
Agent requests additional context or files from the user mid-execution.
Automatic pauses triggered by organizational policies or compliance requirements.
Complex workflows where each step requires user confirmation or input.
Agent pauses when encountering an error, allowing user to provide guidance.
TypeScript SDK:
RunFinishedEvent type with outcome and interrupt fieldsRunAgentInput with resume fieldPython SDK:
RunFinishedEvent classRunAgentInput with resume supportPlanning Frameworks:
Workflow Systems:
Custom Frameworks: