Skip to content

feat(strands): bridge native Strands interrupts to AG-UI interrupt round-trip - #2286

Open
ciolo wants to merge 2 commits into
ag-ui-protocol:mainfrom
ciolo:feat/strands-native-interrupts
Open

feat(strands): bridge native Strands interrupts to AG-UI interrupt round-trip#2286
ciolo wants to merge 2 commits into
ag-ui-protocol:mainfrom
ciolo:feat/strands-native-interrupts

Conversation

@ciolo

@ciolo ciolo commented Jul 30, 2026

Copy link
Copy Markdown

Fixes #2205

Summary

Bridges native Strands tool_context.interrupt() pauses to the AG-UI interrupt lifecycle, so human-in-the-loop flows work over the protocol. Previously a native interrupt either surfaced as RUN_ERROR or silently finished as a completed run, and a client's resume payload was dropped.

This is a wrapper-only change in integrations/aws-strands/python/ — the AG-UI protocol types it relies on already ship in ag-ui-protocol 0.1.19.

I filed #2205 ~2 weeks ago and pinged #-💎-contributing on Discord; opening this PR to move the discussion forward. Happy to adjust scope or approach.

Changes

  • Consume RunAgentInput.resume — builds the Strands resume prompt [{"interruptResponse": {"interruptId", "response"}}] and drives stream_async with it (takes precedence over other stream paths, since a resume run carries no fresh prompt). status="cancelled" resumes with the documented denial sentinel INTERRUPT_CANCELLED = {"cancelled": True}.
  • Detect the pause after the stream loop — inspects the terminal AgentResult (stop_reason == "interrupt"), captured before the complete/force_stop early-break so it's never dropped; falls back to the agent's _interrupt_state.activated if the result event was consumed.
  • Emit RunFinishedInterruptOutcome — one AG-UI Interrupt per Strands interrupt. The Strands interrupt name maps to the categorical AG-UI reason; the free-form Strands reason object is preserved under metadata.strands_reason. Non-interrupt runs still finish bare (no behavior change).
  • Bump ag-ui-protocol floor to >=0.1.19 (ships the interrupt types) and re-lock.
  • Docs — README section on the HITL round-trip and the durable SessionManager requirement for stateless / multi-container deployments (the in-memory per-thread cache only preserves interrupt state within one process).

Test plan

  • New unit tests in tests/test_interrupt.py (6 cases): pause → interrupt outcome, state-fallback detection, no-interrupt-finishes-bare, resolved-resume prompt shape, cancelled sentinel, multi-entry resume.
  • Full suite green: uv run pytest tests/ → 182 passed, 2 skipped.
  • Dojo human_in_the_loop example not included in this PR — happy to add if maintainers want it.

🤖 Generated with Claude Code

…und-trip

Translate native Strands `tool_context.interrupt()` pauses into the AG-UI
interrupt lifecycle so human-in-the-loop flows work over the protocol:

- Consume `RunAgentInput.resume`, building the Strands resume prompt
  `[{"interruptResponse": {"interruptId", "response"}}]`; `status="cancelled"`
  resumes with the `INTERRUPT_CANCELLED` denial sentinel.
- Detect a paused run after the stream loop via the terminal `AgentResult`
  (`stop_reason == "interrupt"`), falling back to the agent's
  `_interrupt_state` when the result event is consumed by the early-break path.
- Emit `RunFinishedInterruptOutcome` with one AG-UI `Interrupt` per Strands
  interrupt (name -> categorical `reason`, original reason under
  `metadata.strands_reason`); non-interrupt runs still finish bare.
- Bump `ag-ui-protocol` floor to >=0.1.19 (ships the interrupt types).
- Document the HITL round-trip and the durable `SessionManager` requirement
  for stateless deployments; add unit tests for all four behaviors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ciolo
ciolo force-pushed the feat/strands-native-interrupts branch from 269a418 to 062cb45 Compare July 30, 2026 10:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: ag_ui_strands: bridge native Strands interrupts to AG-UI

1 participant