diff --git a/contrib/claude/agent.md b/contrib/claude/agent.md index 72208892f..7685154ad 100644 --- a/contrib/claude/agent.md +++ b/contrib/claude/agent.md @@ -41,6 +41,30 @@ type Tool interface { `agent.AsTool(name, description)` wraps an agent as a tool for composition. +## Cancellation semantics + +`ctx.Done()` is a **graceful-suspend signal**, not a hard abort. When the +caller cancels `ctx`, `Run`/`RunStreamed`/`Resume`/`Restore` finish their +in-flight LLM call and tool, persist a checkpoint via the configured +`Checkpointer`, and return `*SuspendedError`. Internally `coreLoop` +shadows the incoming ctx with `context.WithoutCancel(ctx)` and uses the +shadow for every downstream call so the cancel never kills work +in-progress; only the at-boundary check observes the original ctx. + +Implications: + +- A `context.WithTimeout` becomes a "max wall-clock budget then suspend" + — strictly better than today's "deadline kills work outright." +- There is no in-process hard-abort path. Callers that genuinely need + to kill a run terminate the process; stale recovery handles the row. +- Tools that need their own deadline must derive it themselves + (`context.WithTimeout(ctx, ...)` *inside* the tool body). + +The supervisor (`pkg/probo/agent_run_handler.go`) maps a SIGTERM-driven +shutdown broadcast onto a per-run `cancelRun(ErrSuspendForCheckpoint)`, +so the same contract drives both the public Go API and the worker +infrastructure path. + ## Limits - Max turns: 10 (default)