Help us shape the future of Go! Take the 2026 Go Developer Survey

basic-tool-interrupts

command
v1.14.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

This sample demonstrates tool interrupts, which are how Genkit does human in the loop (HITL): a tool pauses generation to ask a person, and resumes with their answer.

transferMoney interrupts when a transfer is large enough to need approving. Interrupting ends the turn with the tool unfinished, so the flow reads the interrupt, decides, and runs a second turn that restarts the tool with the answer attached. The tool then acts on it. (Respond is the other option, answering a call outright instead of letting the tool run again.)

DefineResumableTool takes a third type parameter for what comes back on the resume, so the flow and the tool share one type for the answer:

  • The tool function takes a plain context.Context and an *Approval. The parameter is nil on the first call and set on the resume, so the tool reads a typed value instead of asking whether it was resumed and then pulling metadata out by key.
  • tool.Interrupt pauses with a typed value the flow reads back with ai.InterruptAs.
  • The tool's Interrupted claims the paused call, with its input decoded, and Restart on that call carries a typed Approval back. Nothing on that path can fail, so there is no error to handle.

The approve field stands in for the person: a real app would hand the pending interrupt to a client and run the second turn when they answer.

Run it:

go run .

Or with the Dev UI, to call the flow from a browser and read a trace of both turns at http://localhost:4000/traces:

curl -sL cli.genkit.dev | bash    # install the Genkit CLI, once
genkit start -- go run .

Or over HTTP. The balance carries across requests, so run these in order. Decline a transfer that needs approving, which leaves the money where it is:

curl -N -X POST 'http://localhost:8080/transferFlow?stream=true' \
  -H "Content-Type: application/json" \
  -d '{"data": {"request": "Send $120 to bob", "approve": false}}'

Then approve the same one, which spends it:

curl -N -X POST 'http://localhost:8080/transferFlow?stream=true' \
  -H "Content-Type: application/json" \
  -d '{"data": {"request": "Send $120 to bob", "approve": true}}'

A small transfer needs no approval, so it finishes in one turn:

curl -N -X POST 'http://localhost:8080/transferFlow?stream=true' \
  -H "Content-Type: application/json" \
  -d '{"data": {"request": "Send $20 to alice", "approve": false}}'

Repeating the $120 one now asks for more than is left, which the tool answers outright rather than pausing on.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL