ag-ui-protocol / ag-ui-protocol/ag-ui

[Feature]: Human-in-the-loop interrupt/resume support in Claude Agent SDK integration

Open
#2,180 4 comments 0 reactions 0 assignees View on GitHub
enhancement Integration
Dominant language
Python
Stars
15.9k
Forks
1.4k
Avg merge
1d 17h
Merged PRs (30d)
163

Description

### Pre-flight Checklist

- [x] I have searched existing issues and this hasn't been requested yet.

### Problem or Motivation

The AG-UI protocol (`ag-ui-protocol` 0.1.19) defines the interrupt/resume contract: `RunFinishedInterruptOutcome`, `Interrupt`, `ResumeEntry`, and `RunAgentInput.resume`. However, the Claude Agent SDK integration (`ag-ui-claude-sdk`, latest 0.1.5, and `main`) never emits or consumes these types. The only `interrupt` in `adapter.py`/`session.py` is `interrupt(thread_id)`, which *cancels* the running query. There is no way to pause a Claude run on a tool call, surface a response schema to the client, and resume the same loop with a client-supplied payload.

This blocks the canonical human-in-the-loop use case — tool-approval gating — where the model proposes a mutating tool call and a human must approve (or edit args) before it executes. Today integrators have to build bespoke enforcement (e.g. `PreToolUse` deny + an out-of-band approval surface + a durable ledger + arg replay) instead of using the protocol's first-class interrupt outcome.

### Proposed Solution

Wire the existing protocol types into the Claude adapter:

1. When a run needs human input (e.g. a `PreToolUse`/tool-gate signal), pause the underlying Claude query and emit `RunFinishedEvent` with `RunFinishedInterruptOutcome` containing one `Interrupt` per pending item (carrying `toolCallId` and a `responseSchema`).
2. On the next `RunAgentInput`, read `resume: List[ResumeEntry]`, match each `interrupt_id`, and re-enter the paused loop — applying the resume payload (approve / reject / edited args) to the corresponding tool call.
3. Emit the tool result against the original `toolCallId` so the audit trail spans proposal -> resume -> result.

### Alternatives Considered

- Building enforcement below the SDK via `PreToolUse` deny + retry with `updatedInput`, plus an out-of-band approval UI. This works, but is non-standard, doesn't produce protocol-level interrupt events, and accumulates edge-case complexity (cross-surface arg replay, at-most-once semantics) that a first-class interrupt/resume loop would obviate.
- Upgrading `ag-ui-protocol` to 0.1.19 alone — insufficient, since the adapter doesn't use the new types.

### Additional Context

- Protocol support present as of `ag-ui-protocol` 0.1.19 (`ag_ui/core/events.py`, `ag_ui/core/types.py`).
- Adapter gap confirmed on `main`: `integrations/claude-agent-sdk/python/ag_ui_claude_sdk/{adapter,session,handlers}.py` — no `resume` / `outcome` / `RunFinishedInterruptOutcome` references.
- Happy to contribute a PR if the maintainers agree on the shape.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.