Skip to content

feat: add documentation for TS interrupts#25

Closed
zastrowm wants to merge 51 commits intomainfrom
typescript_interrupts
Closed

feat: add documentation for TS interrupts#25
zastrowm wants to merge 51 commits intomainfrom
typescript_interrupts

Conversation

@zastrowm
Copy link
Copy Markdown
Owner

eliasto and others added 30 commits March 20, 2026 16:41
)

Co-authored-by: Ryan Coleman <rycolez@amazon.com>
…ds-agents#482)

Co-authored-by: Charles Duffy <charles-dyfis-net@users.noreply.github.com>
…trands-agents#699)

Co-authored-by: Strands Agent <217235299+strands-agent@users.noreply.github.com>
…trands-agents#688)

Co-authored-by: agent-of-mkmeral <agent-of-mkmeral@users.noreply.github.com>
Co-authored-by: Mackenzie Zastrow <zastrowm@users.noreply.github.com>
strands-agents#656)

Co-authored-by: Containerized Agent <agent@containerized-strands.local>
…versation-manager in user guide (strands-agents#709)

Co-authored-by: Owen Kaplan <okapl@amazon.com>
Co-authored-by: Strands Agent <217235299+strands-agent@users.noreply.github.com>
Co-authored-by: Strands Agent <217235299+strands-agent@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…ents (strands-agents#693)

Co-authored-by: agent-of-mkmeral <agent-of-mkmeral@users.noreply.github.com>
Co-authored-by: mkmeral <mkmeral@users.noreply.github.com>
Co-authored-by: agent-of-mkmeral <217235299+strands-agent@users.noreply.github.com>
Co-authored-by: Murat Kaan Meral <muratkaanmeral@gmail.com>
agent-of-mkmeral and others added 15 commits April 9, 2026 14:21
…gents#747)

Co-authored-by: agent-of-mkmeral <217235299+strands-agent@users.noreply.github.com>
…st_state (strands-agents#696)

Co-authored-by: agent-of-mkmeral <agent-of-mkmeral@users.noreply.github.com>
strands-agents#714)

Co-authored-by: Kang Zhou <kangzhou1991@gmail.com>
Co-authored-by: Subramanian Chidambaram <subbu10123@gmail.com>
…ands-agents#753)

Co-authored-by: agent-of-mkmeral <agent-of-mkmeral@users.noreply.github.com>
Co-authored-by: Gautam Sirdeshmukh <gsird@amazon.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 20903dd
Status:⚡️  Build in progress...

View logs

@github-actions
Copy link
Copy Markdown

Documentation Preview Failed

The documentation deployment encountered an error. Please check the deployment logs for more details.

@github-actions
Copy link
Copy Markdown

Issue: This PR includes unrelated file deletions that should be in separate PRs.

Three files are modified/deleted that have nothing to do with TypeScript interrupt documentation:

  • designs/0008-proactive-context-compression.md — entire design doc deleted
  • team/DECISIONS.md — "Use LLM-Native Units in Public APIs" decision record removed
  • src/content/docs/user-guide/concepts/model-providers/openai.mdx — GPT-OSS troubleshooting sections removed

Suggestion: Per CONTRIBUTING.md: "please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change." These deletions should be reverted from this PR and submitted separately with their own justification.

</Tab>
<Tab label="TypeScript">

Both `BeforeToolCallEvent` and `BeforeToolsEvent` are interruptible. Interrupting on a `BeforeToolCallEvent` allows users to intercept individual tool calls before execution, while `BeforeToolsEvent` allows intercepting the entire batch of tool calls before any execute.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: The mdx mentions BeforeToolsEvent as a TS-specific interruptible event but the code example only demonstrates BeforeToolCallEvent. Since BeforeToolsEvent is called out as a distinguishing TypeScript capability (batch interception), it would be helpful to show it in action — even a brief snippet.

Suggestion: Add a small BeforeToolsEvent example to the hooks snippet (or a separate snippet) to demonstrate batch-level interruption, since this is a feature Python doesn't have and readers will want to see how it works.

@@ -0,0 +1,199 @@
// @ts-nocheck
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: With @ts-nocheck, none of this code is type-checked, so API signatures, import paths, and property names could silently drift from the actual SDK. This is understandable since the interrupt feature isn't published yet, but it creates a maintenance risk.

Suggestion: Add a TODO or tracking comment noting that @ts-nocheck should be removed once the interrupt feature is published in the SDK, so it gets picked up in a follow-up pass. Something like:

// @ts-nocheck
// TODO: Remove @ts-nocheck once interrupts ship in @strands-agents/sdk


Strands enforces the following rules for interrupts:

<Tabs>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: The Rules sections for Hooks and Tools have significant content duplication between the Python and TypeScript tabs (3 out of 5 bullet points are identical). When the shared rules change, both tabs need to be updated independently, which is error-prone.

Suggestion: Consider keeping the shared rules outside the Tabs and only tabbing the SDK-specific differences. For example:

### Rules

Strands enforces the following rules for interrupts:

- All hooks configured on the interrupted event will execute
- All hooks configured on the interrupted event are allowed to raise an interrupt
- A single hook can raise multiple interrupts but only one at a time

<Tabs>
<Tab label="Python">
- All tools running concurrently are interruptible
- All tools running concurrently that are not interrupted will execute
</Tab>
<Tab label="TypeScript">
- When an interrupt fires mid-batch, completed tool results are preserved...
- Both assistant and tool result messages are appended only after...
</Tab>
</Tabs>

reason: { paths: (event.toolUse.input as { paths: string[] }).paths },
})
if (approval.toLowerCase() !== 'y') {
event.cancel = 'User denied permission to delete files'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: The cancel property is introduced without much explanation of its type behavior. The mdx says "Set to true for a default message or provide a custom cancellation message string" but the code example only shows the string variant (event.cancel = 'User denied permission to delete files').

Suggestion: Consider briefly showing both variants in the hooks example comment or in the Components section so readers can see the true shorthand:

event.cancel = true // default cancellation message
// OR
event.cancel = 'User denied permission to delete files' // custom message

let result = await agent.invoke(`paths=<${JSON.stringify(paths)}>`)

while (result.stopReason === 'interrupt') {
const responses = result.interrupts!.map((interrupt) => ({
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: The Python hooks example shows filtering interrupts by name (if interrupt.name == "myapp-approval") in the response loop, but the TypeScript hooks example doesn't — it responds to all interrupts unconditionally with result.interrupts!.map(...). This makes the TS example less complete as a real-world pattern since in practice you'd typically check the interrupt name.

Suggestion: Add a name check in the TypeScript response loop to match the Python example's pattern and show readers the recommended practice:

const responses = result.interrupts!
  .filter((i) => i.name === 'myapp-approval')
  .map((interrupt) => ({
    interruptResponse: {
      interruptId: interrupt.id,
      response: 'y',
    },
  }))

if (event.toolUse.name !== 'delete_files') return

// Check if user already trusted this approval
if (event.agent.appState.get('myapp-approval') === 't') return
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: The session management example uses event.agent.appState.get('myapp-approval') and event.agent.appState.set(...) but the type annotation on server's prompt parameter uses { interruptResponse: { interruptId: string; response: unknown } }[]. Since this is @ts-nocheck, the type won't be validated, but consider whether unknown is the right type for response here — the mdx says "must be JSON-serializable".

Minor: also, event.agent.appState is accessed within a hook callback — ensure this access pattern (event.agent) is the actual SDK API rather than, say, requiring a separate agent reference. With @ts-nocheck this won't be caught if wrong.

@github-actions
Copy link
Copy Markdown

Assessment: Request Changes

This PR adds well-structured TypeScript examples to the interrupts documentation, following established patterns (snippet markers, Tabs/Tab components, function scoping). The examples cover hooks, tools, and session management — the core interrupt workflows.

Review Categories
  • Scope: The PR includes 3 unrelated file deletions (a design doc, a decision record, and OpenAI troubleshooting content) that should be separated into their own PRs with clear justification.
  • Completeness: BeforeToolsEvent is called out as a TS-specific interruptible event but lacks a code example. The Python hooks example filters interrupts by name in the response loop, but the TS version doesn't — showing a less realistic pattern.
  • Maintainability: Several Rules/Components sections duplicate content across Python and TypeScript tabs. Shared content should live outside the tabs to avoid drift.
  • Type safety: @ts-nocheck is justified since the interrupt API isn't published yet, but a TODO to remove it post-publish would help ensure follow-up.

The interrupt documentation additions are a solid contribution and the TS examples closely mirror the Python patterns.

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.