Documentation
¶
Overview ¶
Package subagent runs specialized agents with isolated contexts. Runner is the typed host-facing API. Tool adapts a Runner for model-driven delegation, including parallel, chain, background, and team execution.
Index ¶
- Constants
- Variables
- type Config
- type RunMeta
- type RunResult
- type Runner
- func (r *Runner) AgentConfig(name string) (Config, bool)
- func (r *Runner) AsTool() *Tool
- func (r *Runner) Run(ctx context.Context, agent, task string) (RunResult, error)
- func (r *Runner) SetEventObserver(fn func(meta RunMeta, ev agentcore.Event))
- func (r *Runner) SetThinkingLevel(agentName string, level agentcore.ThinkingLevel)
- type TeamSpawnRequest
- type TeamSpawnResult
- type TeamSpawner
- type Tool
- func (t *Tool) Description() string
- func (t *Tool) Execute(ctx context.Context, args json.RawMessage) (json.RawMessage, error)
- func (t *Tool) Label() string
- func (t *Tool) Name() string
- func (t *Tool) Schema() map[string]any
- func (t *Tool) SetBgOutputFactory(fn func(taskID, agentName string) (io.WriteCloser, string, error))
- func (t *Tool) SetCreateModel(fn func(name string) (agentcore.ChatModel, error))
- func (t *Tool) SetNotifyFn(fn func(agentcore.AgentMessage))
- func (t *Tool) SetTaskRuntime(rt *task.Runtime)
- func (t *Tool) SetTeamSpawner(fn TeamSpawner)
- type UnknownAgentError
- type Usage
Constants ¶
const ( ModeSingle = "single" ModeParallel = "parallel" ModeChain = "chain" ModeBackground = "background" )
Run modes — the authoritative set of values for RunMeta.Mode. Observers should compare against these rather than string literals.
Variables ¶
var ErrUnknownAgent = errors.New("unknown agent")
ErrUnknownAgent is the sentinel for "agent name not registered with this Runner". Match with errors.Is; use errors.As with *UnknownAgentError to read the requested name and the available set. A host scheduler branches on this to classify the failure as deterministic (retrying the same run cannot succeed) without matching error strings.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
Name string
Description string
// Model is resolved when each sub-agent run starts. Wrappers that swap the
// underlying model at runtime (e.g. agentcore.SwappableModel) take effect
// on the next sub-agent run.
Model agentcore.ChatModel
SystemPrompt string
// SystemPromptMode is a host-interpreted hint controlling how
// SystemPrompt composes with the host's base prompt. agentcore does
// NOT consume this field — the team spawner / executor on the host
// side reads it to assemble AgentContext.SystemBlocks. Kept as a
// plain string at the boundary so agentcore stays agnostic to enum
// values that only matter inside one host; empty / unrecognized
// values fall back to the host's default mode.
SystemPromptMode string
Tools []agentcore.Tool
MaxTurns int
// ToolGate, when non-nil, is called once per tool call in this
// sub-agent's runs — same contract as agentcore.WithToolGate for
// top-level agents (nil decision = allow, UpdatedArgs rewrites the
// executed arguments). Without it a sub-agent's tools run ungated, so
// a harness with a permission system should thread its gate here.
ToolGate agentcore.ToolGate
// Middlewares wrap each tool execution in this sub-agent's runs
// (outermost first). Mirrors agentcore.WithMiddlewares.
Middlewares []agentcore.ToolMiddleware
// ThinkingLevel sets the reasoning depth for this sub-agent's runs.
// Empty ("") leaves it unspecified (model/provider default). Mirrors
// agentcore.WithThinkingLevel for top-level agents. A runtime override
// installed via Runner.SetThinkingLevel takes precedence over this baseline.
ThinkingLevel agentcore.ThinkingLevel
// MaxRetries caps the LLM call retry count for retryable errors within
// this sub-agent's loop. 0 (default) disables retry entirely.
MaxRetries int
// StopAfterTools lists tool names that trigger early loop exit after
// successful execution.
StopAfterTools []string
// StopAfterToolResult is the result-aware variant of StopAfterTools.
StopAfterToolResult func(toolName string, result json.RawMessage) bool
// OnMessage, if non-nil, is called after each message is appended to
// context. The agentName and task are provided for session routing.
OnMessage func(agentName, task string, msg agentcore.AgentMessage)
// Optional context lifecycle hooks for long-running sub-agents.
ContextManager agentcore.ContextManager
ContextManagerFactory func(model agentcore.ChatModel) agentcore.ContextManager
ConvertToLLM func(msgs []agentcore.AgentMessage) []agentcore.Message
// CacheLastMessage, when non-empty, tags the last non-system message of
// every LLM request in this sub-agent's loop with the given cache_control
// value ("ephemeral", or "ephemeral:1h" for extended TTL). Mirrors
// agentcore.WithCacheLastMessage for top-level agents; see that option
// for placement semantics.
CacheLastMessage string
// PromptCacheKey is the base prompt-cache routing identity for this
// sub-agent's LLM requests. Each spawn appends "#<seq>" so every run gets
// its own cache lineage — one conversation, one key — which providers
// with key-routed prefix caching (OpenAI prompt_cache_key) use to keep a
// session's requests on the same cache shard. Empty sends no hint.
PromptCacheKey string
// StopGuardFactory, if non-nil, creates a fresh StopGuard for each run.
StopGuardFactory func(agentName, task string) agentcore.StopGuard
}
Config defines a sub-agent's identity and capabilities.
type RunMeta ¶ added in v1.7.0
RunMeta identifies one sub-agent run for an external event observer. It lets a harness route a run's raw AgentLoop events to a per-run sink (e.g. a live-preview transcript) without the subagent tool knowing anything about that sink.
- Agent: the agent definition/type name (e.g. "explore"). Not unique when the same type runs more than once concurrently (parallel mode).
- InstanceID: unique per run invocation within this Runner's lifetime. Use this — not Agent — as the routing key.
- Mode: one of the Mode* constants below.
type RunResult ¶ added in v1.7.10
type RunResult struct {
// Agent is the registered agent definition that ran.
Agent string
// Output is the final assistant text. Unlike the LLM tool-call surface,
// it is NOT concatenated with TerminalResult and has no "(no output)"
// placeholder — an agent that only called tools yields "".
Output string
// TerminalResult is the successful result of the tool that triggered a
// StopAfterTools / StopAfterToolResult exit, nil when the run ended some
// other way.
TerminalResult json.RawMessage
// Usage carries aggregated counters. Populated on both success and
// failure paths (a run that errors mid-way still consumed tokens);
// zero-valued when the run never started (e.g. unknown agent).
Usage Usage
}
RunResult is the typed outcome of one sub-agent run.
type Runner ¶ added in v1.7.13
type Runner struct {
// contains filtered or unexported fields
}
Runner executes registered agents through AgentLoop. It owns only agent definitions and per-run behavior; model-facing JSON and background/team orchestration live in Tool.
func NewRunner ¶ added in v1.7.13
NewRunner creates a Runner from the supplied agent definitions. It panics when an agent name is empty or duplicated because the registry is static program configuration and either condition is a programming error.
func (*Runner) AgentConfig ¶ added in v1.7.13
AgentConfig returns the registered sub-agent definition for name, or (zero, false) if none is registered. Exposed read-only so a harness can rebuild a TeamSpawnRequest when resuming a teammate by its agent type without re-deriving the config from scratch.
func (*Runner) AsTool ¶ added in v1.7.13
AsTool exposes model-driven delegation backed by this Runner.
func (*Runner) Run ¶ added in v1.7.13
Run executes one registered sub-agent programmatically. Inputs and outputs are typed, and failures are Go errors carrying the loop's full chain (errors.Is(err, ErrUnknownAgent) for lookup failures, agentcore.ErrStopGuard / ErrMaxTurns / provider sentinels for loop failures — see agentcore.ErrorKind for the stable taxonomy).
Everything configured on the agent's Config applies exactly as in the tool-call path: StopGuard, StopAfterTools, OnMessage, context management, prompt-cache keys. Progress reporting via agentcore.WithToolProgress on ctx works identically.
func (*Runner) SetEventObserver ¶ added in v1.7.13
SetEventObserver installs a callback that receives every raw AgentLoop event produced by any sub-agent run (single/parallel/chain/background), tagged with a RunMeta carrying a unique per-run InstanceID. A harness uses this to drive a live preview of sub-agent work — symmetric to how a teammate executor fans its loop events out. nil (the default) disables observation with zero cost.
The callback MUST be non-blocking: it runs inline on the sub-agent's execution goroutine (and on parallel/background goroutines concurrently), so a slow observer stalls the run. Sinks that may block should buffer + drop.
func (*Runner) SetThinkingLevel ¶ added in v1.7.13
func (r *Runner) SetThinkingLevel(agentName string, level agentcore.ThinkingLevel)
SetThinkingLevel overrides a sub-agent's reasoning depth at runtime, keyed by agent name. It takes effect on the next run of that agent (mirroring how a SwappableModel swap takes effect on the next run) and overrides the agent's Config.ThinkingLevel baseline. Safe to call concurrently with running agents: the override lives in an isolated map and never mutates the immutable agents config map. Empty level ("") means model/provider default.
type TeamSpawnRequest ¶ added in v1.6.10
type TeamSpawnRequest struct {
// Config is the resolved sub-agent definition the teammate runs as.
// Spawner reads SystemPrompt, Tools, Model, MaxTurns etc. from here.
Config Config
// Name is the teammate's identifier inside the team (routing key for
// send_message). May equal Config.Name when the LLM did not specify one.
Name string
// TeamName is the active team's name; spawner validates against registry.
TeamName string
// InitialPrompt is the leader's first message to the teammate.
InitialPrompt string
// Description is an optional one-line summary for transcripts/UI.
Description string
// Color is an optional UI color assigned to this teammate.
Color string
// Model is non-nil when the LLM requested an override; nil means the
// spawner should fall back to Config.Model.
Model agentcore.ChatModel
// History, if non-empty, seeds the teammate's conversation before its
// first turn — the spawner forwards it to team.SpawnConfig.History. The
// LLM never sets this; a harness populates it when resuming a teammate
// with its prior transcript after a restart. nil ⇒ fresh teammate.
History []agentcore.AgentMessage
}
TeamSpawnRequest is the contract between the subagent tool and the codebot-side team spawner. The subagent tool builds this from its params after validating the requested agent definition exists; the spawner is responsible for the actual goroutine launch, tool augmentation (e.g. injecting send_message), and team registry bookkeeping.
type TeamSpawnResult ¶ added in v1.6.10
TeamSpawnResult is what the spawner returns synchronously. The teammate itself runs in the background; callers terminate it via task.Runtime.Stop (by TaskID) or by the team's shutdown protocol.
type TeamSpawner ¶ added in v1.6.10
type TeamSpawner func(ctx context.Context, req TeamSpawnRequest) (*TeamSpawnResult, error)
TeamSpawner is the function shape codebot installs via SetTeamSpawner. Kept as a function rather than an interface because the subagent tool only needs one method and call sites are simpler with a closure.
type Tool ¶
type Tool struct {
// contains filtered or unexported fields
}
Tool implements agentcore.Tool as an adapter over Runner.
func (*Tool) Description ¶
func (*Tool) Execute ¶
func (t *Tool) Execute(ctx context.Context, args json.RawMessage) (json.RawMessage, error)
func (*Tool) SetBgOutputFactory ¶
func (t *Tool) SetBgOutputFactory(fn func(taskID, agentName string) (io.WriteCloser, string, error))
SetBgOutputFactory sets the factory that creates output writers for background tasks. The factory receives the task ID and agent name and returns a writer, file path, and error.
func (*Tool) SetCreateModel ¶
SetCreateModel sets the factory for resolving model names to ChatModel instances at runtime. Enables LLM to override the default model per call.
func (*Tool) SetNotifyFn ¶
func (t *Tool) SetNotifyFn(fn func(agentcore.AgentMessage))
SetNotifyFn sets the callback invoked when a background task completes. Typically bound to Agent.FollowUp so the main agent receives the result as a follow-up message.
func (*Tool) SetTaskRuntime ¶
SetTaskRuntime sets the shared task runtime for background task registration. Required for background mode.
func (*Tool) SetTeamSpawner ¶ added in v1.6.10
func (t *Tool) SetTeamSpawner(fn TeamSpawner)
SetTeamSpawner installs the closure that handles team-spawn mode. Without it, calls that set name or team_name are rejected with a clear error so the LLM learns the feature is unavailable rather than silently downgrading to a regular subagent run.
type UnknownAgentError ¶ added in v1.7.10
UnknownAgentError reports a lookup failure against the Runner's registry. errors.Is matches ErrUnknownAgent.
func (*UnknownAgentError) Error ¶ added in v1.7.10
func (e *UnknownAgentError) Error() string
func (*UnknownAgentError) Is ¶ added in v1.7.10
func (e *UnknownAgentError) Is(target error) bool
type Usage ¶ added in v1.7.10
type Usage struct {
Input int `json:"input"`
Output int `json:"output"`
CacheRead int `json:"cache_read"`
CacheWrite int `json:"cache_write"`
Cost float64 `json:"cost"`
Turns int `json:"turns"`
Tools int `json:"tools"`
}
Usage aggregates token consumption and loop counters for one sub-agent run.