Documentation
¶
Overview ¶
Package spawn registers the spawn / supervise tools the root agent uses to manage workers. See .agents/WORKER_RUNTIME.md for the canonical schemas; the implementations here delegate to the workers.Manager so the LLM never reaches into manager internals.
Phase 5 scope: static workers only. Dynamic-worker tools land in Phase 6 alongside the validator that ensures spec.MCPs/Skills are a subset of the universe baifo knows.
Index ¶
- func OpaqueToolNames() []string
- type BatchSpawnArgs
- type BatchSpawnResult
- type CollectArgs
- type CollectResult
- type DynamicLLM
- type DynamicSpawnArgs
- type InspectArgs
- type KillArgs
- type KillResult
- type ListResult
- type NamedDescription
- type QueryArgs
- type QueryResult
- type RootDefaults
- type SpawnResult
- type SpawnStaticArgs
- type TemplateResolver
- type TemplateSummary
- type TemplatesResult
- type Tools
- type Universe
- type WorkerSummary
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func OpaqueToolNames ¶
func OpaqueToolNames() []string
OpaqueToolNames returns the names of every tool this package registers whose arguments must NOT be walked by the secrets expander. They are the spawn tools, and the reason is structural: their args carry the child agent's full spec — prompt, initial message, allowed_secrets list, sandbox path, etc. If the expander rewrote a ${secret:NAME} placeholder appearing inside that spec, the raw value would land in the child agent's prompt at construction time, bypassing the child's own allowlist (which is usually narrower than the parent's, often empty).
Keeping the placeholders intact lets them propagate verbatim into the child's prompt. The child's own BeforeToolCallback then runs the expander at the child's own tool boundary, with the child's own allower in effect. That is the right gate for the allowed-secrets subset rule documented in DECISIONS.md #10 to be load-bearing rather than merely advisory.
The list is kept here (not in internal/secrets or internal/agent) because this package is the source of truth for which spawn tools exist. Adding a new spawn-style tool means updating this list in the same commit; the agent.Builder reads it through Builder.OpaqueTools without knowing what "spawn" means.
Returns a fresh slice on every call so callers cannot mutate the internal table by accident. Order matches the registration order in ADKTools().
Types ¶
type BatchSpawnArgs ¶
type BatchSpawnArgs struct {
Agents []DynamicSpawnArgs `json:"agents"`
}
BatchSpawnArgs is the input of spawn_dynamic_agents — pure convenience over calling spawn_dynamic_agent N times in one turn.
type BatchSpawnResult ¶
type BatchSpawnResult struct {
WorkerIDs []string `json:"worker_ids"`
}
BatchSpawnResult mirrors SpawnResult but for the batch tool.
type CollectArgs ¶
type CollectArgs struct {
WorkerID string `json:"worker_id"`
TimeoutMs int `json:"timeout_ms,omitempty"`
}
CollectArgs is the input of collect_agent.
type CollectResult ¶
type CollectResult struct {
Output string `json:"output"`
Status string `json:"status"`
Err string `json:"error,omitempty"`
}
CollectResult is the response shape: output text + final status.
type DynamicLLM ¶
type DynamicLLM struct {
Provider string `json:"provider,omitempty"`
Model string `json:"model,omitempty"`
// Reasoning optionally sets how hard the worker thinks for models
// that support it: one of "minimal" / "low" / "medium" / "high"
// (empty = the model's default). Call list_models to see which
// models accept reasoning and at which levels.
Reasoning string `json:"reasoning,omitempty"`
}
DynamicLLM is the per-spawn LLM override. When unset the worker inherits the root agent's provider+model (resolved at build time).
type DynamicSpawnArgs ¶
type DynamicSpawnArgs struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Prompt string `json:"prompt"`
LLM DynamicLLM `json:"llm,omitempty"`
Skills []string `json:"skills,omitempty"`
MCPs []string `json:"mcps,omitempty"`
AllowedSecrets []string `json:"allowed_secrets,omitempty"`
InitialMessage string `json:"initial_message,omitempty"`
}
DynamicSpawnArgs is the input of spawn_dynamic_agent. Mirrors the schema in WORKER_RUNTIME.md. ContextGuard is omitted in v1; the builder ignores the field until contextguard is wired in.
type InspectArgs ¶
type InspectArgs struct {
WorkerID string `json:"worker_id"`
SinceEvent int `json:"since_event,omitempty"`
}
InspectArgs is the input of inspect_agent. SinceEvent is reserved for the day the manager keeps a per-worker ring buffer of events.
type KillArgs ¶
type KillArgs struct {
WorkerID string `json:"worker_id"`
// Reason is an optional explanation surfaced on the subsequent
// collect_agent call as CollectResult.Err. The LLM can use it to
// pass context ("superseded by newer plan", "worker stuck on
// rate-limit", ...). Empty defaults to "killed by agent".
Reason string `json:"reason,omitempty"`
}
KillArgs is the input of kill_agent.
type KillResult ¶
type KillResult struct {
OK bool `json:"ok"`
}
KillResult mirrors QueryResult: a simple acknowledgment.
type ListResult ¶
type ListResult struct {
Workers []WorkerSummary `json:"workers"`
}
ListResult is the response shape of list_running_agents.
type NamedDescription ¶
NamedDescription is the shape Universe.SkillDetails / SecretDetails return. Kept in this package (not borrowed from internal/app) so the spawn tools stay free of import cycles and tests can build trivial fakes.
type QueryResult ¶
type QueryResult struct {
OK bool `json:"ok"`
}
QueryResult is what the root sees after enqueueing a follow-up.
type RootDefaults ¶
RootDefaults is the fallback LLM the dynamic-spawn tool applies when args.LLM is unset. The App fills this from cfg.Root.LLM at startup so workers spawned without an explicit provider inherit the root's.
type SpawnResult ¶
type SpawnResult struct {
WorkerID string `json:"worker_id"`
}
SpawnResult is the result returned by both spawn tools.
type SpawnStaticArgs ¶
type SpawnStaticArgs struct {
Name string `json:"name"`
InitialMessage string `json:"initial_message"`
AllowedSecrets []string `json:"allowed_secrets,omitempty"`
}
SpawnStaticArgs is the input of spawn_static_agent.
type TemplateResolver ¶
type TemplateResolver interface {
Resolve(name string) (config.AgentTemplate, bool)
// ListTemplates returns every static-agent template currently
// declared, in a stable order. Used by list_agents and by the
// spawn_static_agent description so the LLM can see what is
// actually available without trial-and-error.
ListTemplates() []config.AgentTemplate
}
TemplateResolver looks up a static-agent template by name in the loaded agents.yaml. The Manager wiring builds the closure; we keep the dependency narrow so this package does not import internal/app.
type TemplateSummary ¶
type TemplateSummary struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Provider string `json:"provider,omitempty"`
Model string `json:"model,omitempty"`
}
TemplateSummary is the per-template row returned by list_agents. Description is the one-line note the user wrote in agents.yaml; the LLM uses it to pick the right template for the task at hand.
type TemplatesResult ¶
type TemplatesResult struct {
Templates []TemplateSummary `json:"templates"`
}
TemplatesResult is the response shape of list_agents.
type Tools ¶
type Tools struct {
Manager *workers.Manager
Templates TemplateResolver
// The next three fields are needed only when dynamic spawning is
// enabled. Static-only deployments can leave them zero.
Universe Universe
RootDefaults RootDefaults
EnableDynamic bool
// ParentAllowedSecrets is the universe of secrets the spawning
// agent itself can dereference. It bounds what its spawn calls
// (static and dynamic) may grant to children — the secrets
// pipeline enforces least-privilege from there.
//
// Two encodings:
//
// - nil → parent is "sovereign": no per-agent
// restriction. Used for the root, which is
// the user-facing coordinator and the
// frontier of trust. Sub-agent allowlists
// are validated against the global universe
// of declared secrets in this mode.
// - non-nil slice → parent's explicit allowlist (possibly
// empty). Sub-agent allowlists must be a
// subset of this list, and an empty list
// means the parent cannot delegate any
// secret.
//
// Today only the root holds spawn tools, so this field is
// effectively always nil in production. The shape is preserved
// for the day a static template gets its own spawn tools.
ParentAllowedSecrets []string
}
Tools bundles the per-spawn dependencies needed to build every tool. Construct one in the App's wiring, then call ADKTools().
type Universe ¶
type Universe interface {
ListSkills() []string
ListMCPs() []string
ListProviders() []string
ListSecretNames() []string
// MCPTools returns the names of the tools exposed by the named
// MCP. Used by the spawn_dynamic_agent description so the LLM
// understands what a worker actually inherits when it lists an
// MCP in its spec — otherwise the model assumes from the MCP
// name alone (e.g. it sees "filesystem" and concludes the MCP
// is read/write only, missing that "exec" lives there too).
// Returns nil for an unknown name; callers should not error.
MCPTools(name string) []string
// MCPExternal reports whether the named MCP uses an external
// transport (http / stdio). Those connect lazily, so their tool
// list is unknown at description-compose time and MCPTools
// returns nil for them — not because the server is empty, but
// because we haven't connected yet. writeMCPs uses this to phrase
// the difference accurately ("tools resolve at call time") instead
// of implying an external MCP advertises nothing.
MCPExternal(name string) bool
// SpawnSkillDetails and SecretDetails enrich the spawn
// description with the metadata the LLM needs to choose well:
// a skill's purpose (from frontmatter) and a secret's intent
// (from the store's description field). Returning empty slices
// is fine — composeDynamicDescription falls back to "(none)".
// Skill variant is namespaced SpawnSkillDetails so it does not
// collide with App.SkillDetails (which already exists for the
// TUI's Settings overlay and returns a different shape).
SpawnSkillDetails() []NamedDescription
SecretDetails() []NamedDescription
}
Universe enumerates the building blocks baifo knows about, used both to validate dynamic spawn specs (per decision #7) and to inject the list into the spawn-tool descriptions so the LLM composes specs from the right vocabulary.
type WorkerSummary ¶
type WorkerSummary struct {
ID string `json:"id"`
Name string `json:"name"`
Kind string `json:"kind"`
Status string `json:"status"`
Elapsed string `json:"elapsed"`
LastEvent string `json:"last_event,omitempty"`
}
WorkerSummary is the per-worker row returned by list_running_agents and inspect_agent. Time-formatted so the LLM can reason about elapsed without re-parsing.