feat(interrupt): implement interrupt system for human-in-the-loop workflows#777
feat(interrupt): implement interrupt system for human-in-the-loop workflows#777
Conversation
…kflows Add comprehensive interrupt support for agent execution pausing: - Implement Interrupt and InterruptState classes to manage interrupt lifecycle - Add interrupt() method to BeforeToolCallEvent and BeforeToolsEvent hooks - Add interrupt() method to ToolContext for use in tool callbacks - Handle InterruptError in agent loop to return stopReason: 'interrupt' - Return interrupts array in AgentResult for inspection The interrupt system allows agents to pause execution at specific points and resume with user responses, enabling human-in-the-loop workflows for approvals, confirmations, and other interactive scenarios. Resolves #479
This comment was marked as off-topic.
This comment was marked as off-topic.
This comment was marked as resolved.
This comment was marked as resolved.
- Export interrupt types from src/index.ts (Interrupt, InterruptError, InterruptState, InterruptParams, InterruptResponse, InterruptResponseContent) - Extract duplicate InterruptError handling into _createInterruptResult() helper - Add interrupt state check after BeforeToolsEvent/BeforeToolCallEvent yields to properly propagate hook interrupts - Implement name-based interrupt matching in getOrCreateInterrupt() for resume across model calls with different tool use IDs - Update jsdoc for _interruptCounter to document serialization exclusion - Add e2e tests for interrupt → response → continue resume flow - Add tests for name-matching behavior in InterruptState Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
…l results When resuming from an interrupt, the agent now: - Skips re-calling the model and uses the stored assistant message - Preserves completed tool results to avoid re-executing successful tools - Only executes the tool that was interrupted (and any remaining tools) Example scenario: If tools A, B, C are requested and A & B succeed but C interrupts, on resume only C executes - A and B are skipped. Implementation: - Add PendingToolExecution interface to store assistant message and completed results - Store pending state when interrupt occurs during tool execution - On resume, check for pending state and skip model invocation - Pass completed tool results to executeTools to skip already-completed tools - Clear pending state when user sends a new message (abandons interrupted flow) This addresses the reviewer feedback that resume should jump directly to tool execution without re-calling the model.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
…ptState
Move the logic for reconstructing assistant message and completed tool
results from agent.ts into InterruptState.getPendingExecution() method.
This provides better encapsulation and makes the agent code cleaner:
- Before: inline reconstruction with Message.fromMessageData() and loop
- After: this._interruptState.getPendingExecution()
The method returns { assistantMessage, completedToolResults } or undefined
if no pending execution exists.
Encapsulation Refactor CompleteAddressed the second feedback item in commit ChangeMoved the pending execution reconstruction logic into // New method signature
getPendingExecution(): {
assistantMessage: Message
completedToolResults: Map<string, ToolResultBlock>
} | undefinedResultThe agent code is now cleaner and the reconstruction logic is encapsulated in the InterruptState class where it belongs. All 1862 tests pass. |
Review Summary - Follow-up ReviewAssessment: Approve All previous feedback has been addressed. The implementation is now complete with proper exports, comprehensive resume flow tests, and the maintainer-requested improvements for skipping model re-invocation on resume. Changes Since Previous ReviewAddressed Issues:
Documentation NoteThis feature adds significant public API surface. Consider a follow-up documentation PR covering:
Well-designed interrupt system that aligns with SDK tenets—simple API entry points, extensible through hooks, and composable with existing patterns. |
Review Summary - Third ReviewAssessment: Approve (No changes needed) The changes since my last review are all improvements - test consolidation following guidelines, better encapsulation ( All previous feedback remains addressed. Ready to merge. |
|
Moved over to #784 |
Motivation
Agents executing tools often need to pause for human approval or input before proceeding with sensitive operations like financial transactions, data modifications, or external API calls. Without a built-in interrupt mechanism, developers must implement custom solutions to handle these human-in-the-loop workflows.
This implementation adds a comprehensive interrupt system that allows agents to:
Resolves #479
Public API Changes
New
interrupt()method on hook events and tool contextTools can now call
interrupt()to pause execution:Hooks can also trigger interrupts:
New
stopReason: 'interrupt'andinterruptsarray on AgentResultWhen an interrupt is triggered, the agent returns immediately:
Use Cases