Skip to content

Commit 987867d

Browse files
chrisraygillclaude
andcommitted
docs(agents): update Go interrupts to the interruptible-tool API
Switch the Go interrupts guide from the older ai.InterruptWith / ctx.IsResumed pattern to genkitx.DefineInterruptibleTool with a typed resume payload, tool.Interrupt/tool.InterruptAs, and the tool's Resume/Respond methods, matching the agents sample and launch surface. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 2eee4c4 commit 987867d

1 file changed

Lines changed: 25 additions & 13 deletions

File tree

src/content/docs/docs/agents/interrupts.mdx

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,14 @@ Wait for the final response before treating the turn as durably interrupted, bec
147147

148148
## Interrupt from a tool
149149

150-
Go does not have a separate interruptible tool type. A normal tool defined with `genkit.DefineTool` signals an interrupt by returning `ai.InterruptWith(ctx, metadata)` from inside its function. The lower-level form is `ctx.Interrupt(&ai.InterruptOptions{Metadata: ...})`.
151-
152-
The tool detects a resumed call with `ctx.IsResumed()` and can read the original input with `ai.OriginalInputAs[T](ctx)`. Keep approval and execution logic in one tool, and require the client to explicitly resume the turn.
150+
Define an interruptible tool with `genkitx.DefineInterruptibleTool`. Its third parameter is a typed *resume payload*: `nil` on the first call, and populated with the client's answer when the turn is resumed. The tool pauses by returning `tool.Interrupt(metadata)`; on resume it runs again from the top with the payload set. Keep approval and execution logic in one tool, and require the client to explicitly resume the turn.
153151

154152
```go
153+
import (
154+
genkitx "github.com/firebase/genkit/go/genkit/exp"
155+
"github.com/firebase/genkit/go/ai/exp/tool"
156+
)
157+
155158
type TransferInput struct {
156159
To string `json:"to"`
157160
Amount float64 `json:"amount"`
@@ -167,16 +170,25 @@ type TransferInterrupt struct {
167170
Reason string `json:"reason"`
168171
}
169172

170-
transferMoney := genkit.DefineTool(g, "transferMoney",
173+
// Confirmation is the resume payload the client sends back to approve or
174+
// reject the paused transfer.
175+
type Confirmation struct {
176+
Approved bool `json:"approved"`
177+
}
178+
179+
transferMoney := genkitx.DefineInterruptibleTool(g, "transferMoney",
171180
"Transfer money after user approval.",
172-
func(ctx *ai.ToolContext, input TransferInput) (TransferOutput, error) {
173-
if !ctx.IsResumed() {
174-
return TransferOutput{}, ai.InterruptWith(ctx, TransferInterrupt{
181+
func(ctx context.Context, input TransferInput, confirm *Confirmation) (TransferOutput, error) {
182+
if confirm == nil {
183+
return TransferOutput{}, tool.Interrupt(TransferInterrupt{
175184
To: input.To,
176185
Amount: input.Amount,
177186
Reason: "Approval is required before transferring money.",
178187
})
179188
}
189+
if !confirm.Approved {
190+
return TransferOutput{}, errors.New("transfer rejected by user")
191+
}
180192

181193
return TransferOutput{ConfirmationID: "txn-123"}, nil
182194
},
@@ -203,21 +215,21 @@ for chunk, err := range conn.Receive() {
203215
}
204216
```
205217

206-
Use `ai.InterruptAs[T]` to decode typed interrupt metadata:
218+
Use `tool.InterruptAs[T]` to decode typed interrupt metadata:
207219

208220
```go
209-
meta, ok := ai.InterruptAs[TransferInterrupt](interrupts[0])
221+
meta, ok := tool.InterruptAs[TransferInterrupt](interrupts[0])
210222
if ok {
211223
fmt.Printf("Approve transfer to %s?", meta.To)
212224
}
213225
```
214226

215227
## Resume an interrupted turn
216228

217-
Build resume parts from the tool, then send them with `conn.SendResume`. Use `RestartWith` to re-execute the original tool, optionally with `ai.WithNewInput` to change its arguments. The tool runs again with `ctx.IsResumed()` true.
229+
Build resume parts from the tool, then send them with `conn.SendResume`. Use `Resume` to re-execute the tool, delivering the client's typed answer to its resume parameter. The tool runs again from the top, this time with a non-nil payload.
218230

219231
```go
220-
part, err := transferMoney.RestartWith(interrupts[0])
232+
part, err := transferMoney.Resume(interrupts[0], Confirmation{Approved: true})
221233
if err != nil {
222234
return err
223235
}
@@ -229,10 +241,10 @@ if err := conn.SendResume(&aix.ToolResume{
229241
}
230242
```
231243

232-
Use `RespondWith` when the result should be the tool output and the tool should not run again, such as a rejected approval:
244+
Use `Respond` when the result should be the tool output and the tool should not run again, such as supplying a precomputed result:
233245

234246
```go
235-
part, err := transferMoney.RespondWith(interrupts[0], TransferOutput{
247+
part, err := transferMoney.Respond(interrupts[0], TransferOutput{
236248
ConfirmationID: "manual-approval",
237249
})
238250
if err != nil {

0 commit comments

Comments
 (0)