Documentation
¶
Overview ¶
Package agentkit is a Go agent SDK.
The loop, the tool system and the provider abstraction are ordinary Go you can read and step through. Nothing is hidden inside a subprocess or a graph engine.
The canonical vocabulary — messages, content blocks, events, Tool and every interface seam — lives in the core package and is used directly. What lives here is the driver — Config, New, the Agent and the loop — and the tool side the driver is built on, which stands without a model. A Toolset is the tools, the policy that selects among them, the guard, the after-interceptor and the sink for execution events; NewRunner validates one into a Runner, which runs tool calls (Call, Batch), code mode included, through the pipeline an agent run uses. An Agent holds a Runner, and Config takes a Toolset. The prompt assembler and the execute guard are each their own package beneath this one.
Index ¶
- Constants
- type Agent
- func (a *Agent) Messages() core.Messages
- func (a *Agent) ReachableTools() []core.Tool
- func (a *Agent) Resolution() Resolution
- func (a *Agent) Run(ctx context.Context, prompt string) (core.RunResult, error)
- func (a *Agent) Runner() *Runner
- func (a *Agent) Stream(ctx context.Context, prompt string) (*core.EventStream, error)
- func (a *Agent) Usage() core.Usage
- type Config
- type Effort
- type PruneOptions
- type Resolution
- type Runner
- type Toolset
Constants ¶
const ( EffortLow = core.EffortLow EffortMedium = core.EffortMedium EffortHigh = core.EffortHigh EffortXHigh = core.EffortXHigh EffortMax = core.EffortMax )
The efforts a Config can ask for.
const DefaultMaxTokens = 32768
DefaultMaxTokens is the output bound sent when Config.MaxTokens is zero. It is still capped at the model's own output cap; a caller who wants the whole cap says so. Providers size rate-limit reservations from max_tokens at request start, so defaulting to a 128K cap costs 128K of output-per-minute budget per turn and removes the only bound on a runaway turn. 32K is generous for tool-call-shaped output.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Agent ¶
type Agent struct {
// contains filtered or unexported fields
}
Agent runs prompts against one model with one tool set. It has no global state: a second agent is a second value.
Its surface is seven methods. Run and Stream execute a prompt to a stop condition; Messages, Usage and ReachableTools read its state, Runner returns the runner its tool calls go through, and Resolution reports the provider, model and effort it was built to run, all safe from any goroutine while a run is in flight. A Run or Stream that overlaps another fails with core.ErrBusy rather than queueing: a prompt queued behind a running one was written against a transcript the caller could see, and by the time it ran the transcript would have changed underneath it.
func New ¶
New builds an Agent from cfg. It runs Resolve first, so what it runs is what Resolve reports, and then validates the Toolset with NewRunner. It refuses a config the agent could not run safely, and returns the first error in this order, unchanged: the provider, the model, the effort, the credentials, and a Toolset that NewRunner refuses — an invalid tool hierarchy, or a shell tool reachable with no Guard to authorize it. That is a returned error here, rather than a missing key or an unrestricted shell discovered on the first run, and no request has been sent.
func (*Agent) Messages ¶
Messages returns the agent's transcript: every message of every run, as recorded. It is a copy, safe to read while a run is in flight.
func (*Agent) ReachableTools ¶
ReachableTools returns every tool a run of this agent can call: the tools Toolset.Policy resolved, and everything those reach through wrappers. A check that a run is read-only, say, has to look at this set rather than at the top-level tools. It is Runner().Reachable().
func (*Agent) Resolution ¶
func (a *Agent) Resolution() Resolution
Resolution returns the provider, model and effort the agent was built with and the client it calls: what Resolve returns for the same Config. It is a copy, so changing its Model does not change the agent's own row.
func (*Agent) Run ¶
Run sends prompt and runs the loop to a stop condition. The error is the result's own Error: a run that stopped on a limit, a refusal or a failure returns both the result and why.
func (*Agent) Runner ¶
Runner returns the agent's runner: the same pointer on every call, safe to use while a run is in flight. The agent's own tool calls go through it, and so can an embedder's. Calls an embedder makes through it are not part of any run: they do not enter the transcript, they are not counted in Usage, they do not claim the run slot, and their events go to Toolset.Events.
func (*Agent) Stream ¶
Stream runs the loop and returns its event stream. The producer never blocks on the consumer, so abandoning the stream is safe and the result stays available through RunResult.
It returns an error rather than only a pre-closed stream for the one case a caller most often gets wrong — a second run while one is in flight — because a silent ErrBusy inside a stream nobody reads is indistinguishable from a run that produced nothing.
type Config ¶
type Config struct {
// Client is the provider client the agent calls: a test double such as
// provider/faux, or a provider the embedder built or wrapped. When it is
// set the agent builds none and reads no variable. Provider and Model
// still choose the catalog row and the effort.
Client core.ProviderClient
// Provider names the provider that serves Model: one of catalog.Providers,
// matched without regard to case and trimmed. Empty means the first. It
// names the catalog provider even when Client is set.
Provider string
// Model is a tier name (SIMPLE, STANDARD or ADVANCED) or the provider's own
// model id; catalog.Select supplies its limits, prices and, for a tier, its
// effort.
Model string
// Effort is one of the five efforts or empty. Empty takes the tier's effort
// when Model is a tier, and sends none otherwise.
Effort Effort
// Env and Getenv supply the variables the chosen provider reads for its
// credentials and endpoint. A non-empty Env value is used first; an empty
// one falls through to Getenv, and with no Getenv to the process
// environment. An empty value counts as unset. Nothing else reads them.
Env map[string]string
Getenv func(string) string
System string
// Prefix is sent after the system prompt on every request, with a cache
// breakpoint on its last block.
Prefix []core.Message
// Toolset is the agent's tools, the policy that selects among them, the
// guard that authorizes every call and the interceptor that sees every
// result. The zero Toolset is an agent with no tools. New refuses a
// Toolset that NewRunner refuses.
Toolset Toolset
// MaxTurns, MaxCostUSD and Timeout bound a run; zero means unbounded.
MaxTurns int
MaxCostUSD float64
Timeout time.Duration
// Prune ages old tool results out of the request; the zero value is off.
Prune PruneOptions
// MaxTokens caps each response; zero means DefaultMaxTokens.
MaxTokens int
}
Config is everything an Agent is built from.
Provider, Model and Effort choose what runs the agent, and Env and Getenv supply the credentials and endpoints of the provider they choose. Resolve shows what a Config resolves to; New builds an agent on exactly that.
type PruneOptions ¶
type PruneOptions struct {
// Threshold is the fraction of the model's context window the estimated
// request must reach before pruning; zero or less disables it.
Threshold float64
// KeepTurns is how many recent turns keep their tool results whole.
KeepTurns int
}
PruneOptions controls how old tool results leave the request.
type Resolution ¶
type Resolution struct {
// Provider is the canonical provider name: one of catalog.Providers.
Provider string
// Tier is the tier Config.Model named, or empty when it named a model id.
Tier catalog.Tier
// Model is the catalog row, or the provider's fallback row for an id the
// catalog does not list. Model.ID is the id the vendor receives.
Model core.Model
// Effort is the effort requested, normalized: the explicit one, else the
// tier's, else empty, which sends none.
Effort Effort
// Listed reports whether Model is a catalog row and not a fallback.
Listed bool
// Client is the client a run calls: Config.Client when it was set, else the
// one built for Provider.
Client core.ProviderClient
}
Resolution is what a Config resolves to: the provider, the model and the effort an agent runs with, and the client it calls. Resolve returns one without building an agent, and Agent.Resolution reports the one an agent was built with.
func Resolve ¶
func Resolve(cfg Config) (Resolution, error)
Resolve turns the selection fields of cfg (Client, Provider, Model, Effort, Env and Getenv) into what New would run: the catalog's choice for the provider, model and effort, and the client to call.
It makes no request and keeps no state, and every call builds a new client. It reads no variable itself: with Config.Client nil, the chosen provider's own constructor looks up that provider's credential and endpoint (Env first, then Getenv, or the process environment when Getenv is nil; an empty value is unset), and no other provider's code runs. A credential that is missing, or an endpoint the provider cannot use, is an error here, before any run. A host that cannot be reached is not: that is found by the first request.
The errors of catalog.Select and of the provider's constructor are returned unchanged, so errors.Is matches catalog.ErrUnknownProvider, catalog.ErrNoModel, catalog.ErrUnknownEffort, openrouter.ErrNoAPIKey and anthropic.ErrNoCredentials, and the message names the value or the variable. The catalog's are returned even when Config.Client is set, which Resolve then returns as it is, reading no variable.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner runs tool calls with no model: Call runs one and Batch runs several, each through the steps a model's calls go through in an agent run — start event, tool lookup, argument preparation, Guard, the handler with a nested caller attached when the tool reaches other tools, After, end event. That includes code mode: a code_mode tool called through a Runner runs its script and the script's calls to the tools it binds.
A Runner is immutable after NewRunner returns, and safe for concurrent use by any number of goroutines. Only a *Runner from NewRunner or Agent.Runner is supported: the zero Runner has no validated tool set to stand on.
func NewRunner ¶
NewRunner validates ts and returns a Runner over it. It refuses a toolset the agent could not run safely: a tool with neither or both of Handler and Execute, an invalid tool hierarchy, or a shell tool reachable with no Guard to authorize it. The checks run in this order — every registered tool, the policy's resolution, every resolved tool, then the shell guard — and the first failure is returned with a nil Runner. New makes the same checks, by calling NewRunner, so the two refuse exactly the same toolsets with the same errors.
NewRunner copies ts.Tools, so a caller who changes its own slice afterwards does not change the runner.
func (*Runner) Batch ¶
func (r *Runner) Batch(ctx context.Context, calls ...core.ToolUseBlock) []core.ToolResult
Batch runs calls with the rules an agent applies to a turn's calls and returns one result per call, in call order. A ToolExecutionStartEvent is emitted for each call in order during a sequential prepare phase, which also prepares arguments and runs Guard in call order; the abort decision is made once, after prepare and before any handler starts, and a context that is done aborts every call not yet finalized; handlers then run concurrently, one goroutine per call, or in call order when at most one runs or a Sequential tool is among the calls; and finalization (After, the end event, the result event) is serialized under a mutex scoped to the batch.
Call ids are used verbatim, even when empty. Guard sees Batch = calls, Index = the call's position, Assistant nil and TurnCount 0. Zero calls return an empty slice and emit nothing.
A result's Terminate is the call's final vote: the handler's, unless After returned a non-nil Terminate, which replaces it; true for a wrapper whose nested call an interceptor terminated; and, for a call Guard blocked, the guard decision's. Batch acts on no vote — ending a run is the caller's. The text of a result equals the text of the ToolResultMessage the same call produces in a run, unless After edited that message in place: the edit reaches the message the ToolResultEvent carries, and not the result.
func (*Runner) Call ¶
func (r *Runner) Call(ctx context.Context, name string, input json.RawMessage) core.ToolResult
Call runs one tool call, as a batch of one, and returns its result. Every outcome is a result: Call returns no Go error and does not panic.
The call's id is "call_" and 16 lowercase hex characters. An empty or whitespace-only input means {}. The result's Error is a code:
- unknown_tool, for a name that is not in Tools, with the text a run produces. Neither Guard nor a handler runs;
- invalid_arguments, for input that is not a JSON object, arguments that fail the tool's schema, or arguments Guard returned that JSON cannot carry;
- blocked_by_policy, for a call Guard blocked, with its reason ("blocked by policy" when it gave none);
- panic and handler_error, for a handler that panicked or returned an error;
- aborted ("Operation aborted"), for a context that is done before the handler would start.
Guard sees ToolName, ToolUseID, Tool, Arguments and RawInput as in a run, with Batch holding the one call, Index 0, Assistant nil, TurnCount 0 and no parent. A nil Assistant is how a guard tells that no model made the call. The result's Terminate is the call's final vote (see Batch).
type Toolset ¶
type Toolset struct {
// Tools are the tools registered; Policy selects from them.
Tools []core.Tool
// Policy selects from Tools, and from what they reach through wrappers.
Policy core.ToolPolicy
// Guard authorizes every call. It is required when a shell tool is
// reachable.
Guard core.BeforeToolCall
// After sees every finished call, and may vote to end an agent run.
After core.AfterToolCall
// Events receives the execution events of the calls a Runner runs outside
// an agent run; a nil Events discards them. It may be called from several
// goroutines at once, so it must be safe for concurrent use, and it should
// not block: start events are emitted while a batch is prepared, and end
// and result events while a call is finalized, so a sink that waits for
// another call of the same batch to finish never returns. A sink may itself
// call Runner.Call. (*core.EventStream).Push is a
// conforming sink. During an agent run the run's stream receives the events
// of the run's calls and Events is not called for them.
Events func(core.Event)
}
Toolset is the tool side of an agent: the tools, the policy that selects among them, the guard that authorizes every call, the interceptor that sees every result, and the sink for execution events. It holds no model, so NewRunner builds from one what runs tool calls with no Agent, and Config.Toolset gives an Agent the same set. The zero Toolset has no tools, which is valid.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package catalog embeds AgentKit's model catalog and turns a model id into a core.Model descriptor.
|
Package catalog embeds AgentKit's model catalog and turns a model id into a core.Model descriptor. |
|
Package codemode provides a tool that runs a model-written Starlark script whose functions are other tools.
|
Package codemode provides a tool that runs a model-written Starlark script whose functions are other tools. |
|
codesearch
module
|
|
|
Package core holds AgentKit's canonical vocabulary and every interface seam.
|
Package core holds AgentKit's canonical vocabulary and every interface seam. |
|
examples
|
|
|
agentdemo
command
Command agentdemo runs AgentKit end to end with no API key and no network.
|
Command agentdemo runs AgentKit end to end with no API key and no network. |
|
codemode
command
Command codemode shows the code-mode tool: the model writes one Starlark script that calls several tools, filters what they return, and hands back only the answer.
|
Command codemode shows the code-mode tool: the model writes one Starlark script that calls several tools, filters what they return, and hands back only the answer. |
|
codingagent
command
Command codingagent is a coding agent with the built-in file and shell tools, a workspace root, an execute policy and a live event stream.
|
Command codingagent is a coding agent with the built-in file and shell tools, a workspace root, an execute policy and a live event stream. |
|
customtools
command
Command customtools is the reference for writing your own tools: schemas built from combinators, the two handler shapes, error results the model can recover from, per-tool argument repair, sequential execution for tools with side effects, and a terminating submit_answer.
|
Command customtools is the reference for writing your own tools: schemas built from combinators, the two handler shapes, error results the model can recover from, per-tool argument repair, sequential execution for tools with side effects, and a terminating submit_answer. |
|
mcp
command
Command mcp is AgentKit as a Model Context Protocol CLIENT: it borrows another program's tools and hands them to a model.
|
Command mcp is AgentKit as a Model Context Protocol CLIENT: it borrows another program's tools and hands them to a model. |
|
toolbox
command
Command toolbox calls AgentKit's built-in tools by hand, with no model: the same tools an agent gets from tools.For, run through the same agentkit.Runner path an agent's calls take, so you can see what each one takes and returns and try your own arguments.
|
Command toolbox calls AgentKit's built-in tools by hand, with no model: the same tools an agent gets from tools.For, run through the same agentkit.Runner path an agent's calls take, so you can see what each one takes and returns and try your own arguments. |
|
Package guard is the `execute` boundary in non-interactive deployments.
|
Package guard is the `execute` boundary in non-interactive deployments. |
|
internal
|
|
|
diag
Package diag holds the non-fatal report type shared by the code that loads LOCALLY AUTHORED content: the MCP client's configuration and the TOML subset underneath it.
|
Package diag holds the non-fatal report type shared by the code that loads LOCALLY AUTHORED content: the MCP client's configuration and the TOML subset underneath it. |
|
providerconformance
Package providerconformance holds the opt-in live tests of the anthropic, openrouter and ollama providers.
|
Package providerconformance holds the opt-in live tests of the anthropic, openrouter and ollama providers. |
|
testkit
Package testkit holds the Agent-free test doubles the root package's tests use, exported so a test in a package ABOVE the root (such as tools_test) can script a provider the same way.
|
Package testkit holds the Agent-free test doubles the root package's tests use, exported so a test in a package ABOVE the root (such as tools_test) can script a provider the same way. |
|
testutil
Package testutil holds the test helpers that tests of many packages need and that need nothing of AgentKit: file trees, a git environment that ignores the machine's configuration, polling with a deadline, JSON, tar, golden files, the repository root, and running a program with `go run`.
|
Package testutil holds the test helpers that tests of many packages need and that need nothing of AgentKit: file trees, a git environment that ignores the machine's configuration, polling with a deadline, JSON, tar, golden files, the repository root, and running a program with `go run`. |
|
toolconformance
Package toolconformance holds the tool conformance case table: every built-in tool returns its documented error codes, and its Data conforms to its declared OutputSchema.
|
Package toolconformance holds the tool conformance case table: every built-in tool returns its documented error codes, and its Data conforms to its declared OutputSchema. |
|
Package prompt assembles the system prompt the loop sends.
|
Package prompt assembles the system prompt the loop sends. |
|
anthropic
Package anthropic implements the Anthropic Messages wire API.
|
Package anthropic implements the Anthropic Messages wire API. |
|
faux
Package faux is a deterministic provider that replays a scripted sequence of assistant turns.
|
Package faux is a deterministic provider that replays a scripted sequence of assistant turns. |
|
ollama
Package ollama is a core.ProviderClient for a model served by an Ollama server, local or self-hosted.
|
Package ollama is a core.ProviderClient for a model served by an Ollama server, local or self-hosted. |
|
openrouter
Package openrouter is a core.ProviderClient for a model served by OpenRouter.
|
Package openrouter is a core.ProviderClient for a model served by OpenRouter. |
|
Package schema is the structured, transformable tool-schema value type.
|
Package schema is the structured, transformable tool-schema value type. |
|
Package tools provides AgentKit's built-in tool set.
|
Package tools provides AgentKit's built-in tool set. |
|
Package wire is the bounded, strict decoder for bytes AgentKit did not produce.
|
Package wire is the bounded, strict decoder for bytes AgentKit did not produce. |
|
Package workspace is the root every AgentKit scenario opens first: the containment boundary for the file tools, the ignore rules that apply under it and the directory walk that honours them.
|
Package workspace is the root every AgentKit scenario opens first: the containment boundary for the file tools, the ignore rules that apply under it and the directory walk that honours them. |