Files
probo/contrib/claude/agent.md
Bryan Frimin 3dfc833671 Replace supervisor with agentrun worker service
Move agent-run orchestration from the legacy supervisor path into the new
agentrun worker/service package and wire it through coredata, server,
policies, and GraphQL resolvers.

This consolidates run lifecycle handling around lease-aware workers and
aligns API surface with the new agent-run domain model so reviewers can
follow one coherent execution path.

Signed-off-by: Bryan Frimin <bryan@probo.com>
2026-06-08 15:27:50 +02:00

111 lines
3.6 KiB
Markdown

# Agent (`pkg/agent`)
LLM agent orchestration framework.
## Agent construction
```go
agent := agent.NewAgent(
"agent-name",
"System instructions here",
agent.WithTools(tool1, tool2),
agent.WithHandoffs(otherAgent),
agent.WithModel(model),
)
```
Functional options: `WithTools`, `WithHandoffs`, `WithInstructions`, `WithModel`, `WithModelSettings`, `WithMCPServers`, `WithInputGuardrails`, `WithOutputGuardrails`, `WithApproval`, `WithSession`.
## Execution
```go
result, err := agent.Run(ctx, messages)
result.FinalMessage().Text() // final output
result.LastAgent // agent that produced the result
```
Prefer `RunTyped[T]` over `Run` + manual unmarshalling when the agent declares a
structured output type via `WithOutputType`. `RunTyped` validates the response
against the JSON Schema and returns the typed value directly:
```go
result, err := agent.RunTyped[TrackerIdentification](ctx, ag, messages)
identification := result.Output // already typed, no json.Unmarshal needed
```
Only fall back to `agent.Run` when the agent produces free-form text with no
output schema.
## Tool interface
```go
type Tool interface {
Name() string
Description() string
Parameters() jsonschema.Schema
Execute(ctx context.Context, input json.RawMessage) (string, error)
}
```
## Agent-as-tool
`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` let
the in-flight LLM call and tool finish, persist a checkpoint via the
configured `Checkpointer`, and return `*SuspendedError`. The framework
shields downstream calls (LLM, tools, hooks, guardrails, save) from
the cancellation so they complete naturally; the cancel is only
observed at the next safe boundary.
Use `agent.ErrSuspendForCheckpoint` as the cancel cause when the
intent is graceful suspend — workers that distinguish a
graceful-stop request from infrastructure-level causes (lease loss,
heartbeat failure) inspect `context.Cause(ctx)` to dispatch.
Implications:
- A `context.WithTimeout` becomes a "max wall-clock budget then
suspend" — strictly better than the alternative where the 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 receive a non-cancellable ctx; if a tool needs a hard deadline
it must derive its own with `context.WithTimeout(ctx, ...)` inside
the tool body.
The agent run worker (`pkg/agentrun/handler.go`) maps a SIGTERM-driven
shutdown broadcast onto a per-run `cancelRun(agent.ErrSuspendForCheckpoint)`,
so the same contract drives both the public Go API and the worker
infrastructure path.
## Prompt templates
Prompt files with placeholders use `.txt.tmpl` (see general template naming
convention in `.cursor/rules/template-files.mdc`).
Use `agent.WithInstructionsFunc` to build prompts dynamically at runtime:
```go
//go:embed prompts/tracker_identification.txt.tmpl
var trackerIdentificationPrompt string
func trackerMappingInstructions(_ context.Context, _ *agent.Agent) string {
categories := coredata.ThirdPartyCategories()
parts := make([]string, len(categories))
for i, c := range categories {
parts[i] = string(c)
}
return strings.Replace(trackerIdentificationPrompt, "{{.Categories}}", strings.Join(parts, ", "), 1)
}
```
## Limits
- Max turns: 10 (default)
- Max tool depth: 16 (default)
- Depth tracking prevents infinite recursion in handoffs