Skip to content

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

Description

@Sri01728

Pre-flight Checklist

  • 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions