Documentation
¶
Overview ¶
Package subagent implements sub-agents: isolated agent loops that run with their own fresh context while sharing the main provider adapter and tool set. The model can delegate a focused task (or several tasks in parallel) and receive each sub-agent's final answer — the building block for task decomposition and parallel research, mirroring opencode's sub-agents.
Safety: a sub-agent runs with a sub-registry that (1) drops the interactive tools (ask_user, review_changes) and the subagent tool itself (no recursion), and (2) denies every gated command — destructive shell operations always require the main agent's approval modal, never a silent background run.
Index ¶
- func Merge(reports []string) string
- type Role
- type RunMetrics
- type Runner
- func (r *Runner) ExecuteSwarm(ctx context.Context, task SwarmTask, onUpdate loop.TurnOutputHandler) (*SwarmResult, error)
- func (r *Runner) Run(ctx context.Context, task string) (string, error)
- func (r *Runner) RunMany(ctx context.Context, agents []SubAgent, parallel bool, ...) ([]string, error)
- func (r *Runner) RunScoutSwarm(ctx context.Context, subpaths []string, goal string) string
- func (r *Runner) RunWithProgress(ctx context.Context, task, mode string, onUpdate loop.TurnOutputHandler) (string, error)
- type ScoutJob
- type ScoutManager
- func (sm *ScoutManager) Cancel(id string)
- func (sm *ScoutManager) CancelAll()
- func (sm *ScoutManager) Drain() []string
- func (sm *ScoutManager) Pending() int
- func (sm *ScoutManager) Start(ctx context.Context, task string) (string, error)
- func (sm *ScoutManager) StartWithProgress(ctx context.Context, task string, onProgress func(string)) (string, error)
- type ScoutTool
- type SubAgent
- type SwarmResult
- type SwarmTask
- type SwarmTool
- type Tool
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Merge ¶
Merge combines per-sub-agent reports into one concise, de-duplicated summary. It keeps the per-agent structure (### headers and **Status:** lines are always preserved) but collapses identical content lines that several agents repeat (the same error message, the same file path) so the merged view is small enough to drop straight back into the main context without re-bloating it.
Types ¶
type RunMetrics ¶ added in v0.1.1
RunMetrics carries a finished sub-agent run's answer plus the tokens and estimated cost it consumed, so callers (the swarm, /cost breakdowns) can attribute usage to a specific phase instead of lumping everything together.
type Runner ¶
type Runner struct {
Adapter provider.ProviderAdapter
Model string
// CheapModel, when set, routes mechanical specialist roles (swarm BUILDER /
// AUDITOR) to a cheaper model so reasoning-heavy roles (ARCHITECT) can use
// the strong Model without paying flagship prices for mechanical work.
// Empty = every role uses Model. Sub-agent/scout tasks always use Model.
CheapModel string
Tools *tool.Registry // the main registry; sub-agents get a safe subset
// BudgetUSD, when > 0, caps each sub-agent turn's estimated provider spend
// (hard stop → graceful synthesis). Runaway sub-agents can no longer burn
// tokens to the 10-minute wall-clock cap with no cost limit.
BudgetUSD float64
// Store, when non-nil, persists each sub-agent's isolated conversation to
// SQLite so delegated work is auditable after the fact. Nil keeps the
// previous behavior (fresh context, nothing persisted).
Store *store.Store
// Ask, when set, is the confirmation gate for MUTATING parallel tasks. A
// sub-agent flagged Mutates (write/delete/exec) must be explicitly approved
// by the user before it runs — this is the "controlled" half of BroCode's
// parallel orchestration: fan-out is free and fast, but any side-effecting
// parallel agent cannot act without a confirm. Nil = deny mutating tasks.
Ask func(question string, options []string) (string, error)
// ContextWindow is the token limit for sub-agent contexts. 0 defaults to 128k.
ContextWindow int
}
Runner executes isolated sub-agent turns against the same provider adapter the main loop uses.
func (*Runner) ExecuteSwarm ¶
func (r *Runner) ExecuteSwarm(ctx context.Context, task SwarmTask, onUpdate loop.TurnOutputHandler) (*SwarmResult, error)
ExecuteSwarm coordinates a 3-tier specialist swarm (Architect -> Builder -> Auditor). It runs each specialist with dedicated mode isolation, budget bounds, and progress streaming.
func (*Runner) RunMany ¶
func (r *Runner) RunMany(ctx context.Context, agents []SubAgent, parallel bool, onUpdate loop.TurnOutputHandler) ([]string, error)
RunMany executes the given tasks — concurrently when parallel is true, sequentially otherwise — and returns one report per task. Completed agents stream a one-line progress update through onUpdate (may be nil) so the caller sees results arrive incrementally instead of waiting for the whole batch.
func (*Runner) RunScoutSwarm ¶
RunScoutSwarm executes parallel speculative research subagents across different subdirectories, returning aggregated findings without polluting the main conversation (Inovasi 1).
func (*Runner) RunWithProgress ¶ added in v0.1.32
func (r *Runner) RunWithProgress(ctx context.Context, task, mode string, onUpdate loop.TurnOutputHandler) (string, error)
RunWithProgress executes a single sub-agent and streams live progress updates through onUpdate.
type ScoutJob ¶
type ScoutJob struct {
ID string
Task string
Done bool
Result string
Err error
// contains filtered or unexported fields
}
ScoutJob is one background research task.
type ScoutManager ¶
type ScoutManager struct {
Runner *Runner
// contains filtered or unexported fields
}
ScoutManager owns the background scout jobs for a session.
func NewScoutManager ¶
func NewScoutManager(r *Runner) *ScoutManager
NewScoutManager creates a scout manager backed by the given runner.
func (*ScoutManager) Cancel ¶
func (sm *ScoutManager) Cancel(id string)
Cancel aborts a single running scout by its job id. Already-completed jobs are untouched.
func (*ScoutManager) CancelAll ¶
func (sm *ScoutManager) CancelAll()
CancelAll aborts every running scout. Used when the session is interrupted or the program exits so background goroutines are not left dangling.
func (*ScoutManager) Drain ¶
func (sm *ScoutManager) Drain() []string
Drain collects all completed-but-undelivered scout results and removes them from the manager. Returns one formatted report per finished job. Running jobs are left in place.
func (*ScoutManager) Pending ¶
func (sm *ScoutManager) Pending() int
Pending returns the number of scouts still running.
func (*ScoutManager) Start ¶
Start launches a background scout. Returns the job id immediately; the job runs in its own goroutine and its result is picked up by Drain.
func (*ScoutManager) StartWithProgress ¶
func (sm *ScoutManager) StartWithProgress(ctx context.Context, task string, onProgress func(string)) (string, error)
StartWithProgress launches a background scout, forwarding its progress lines to onProgress (may be nil). Returns the job id immediately.
type ScoutTool ¶
type ScoutTool struct {
Manager *ScoutManager
}
ScoutTool is the native `scout` tool: it starts background research and returns immediately. Results are delivered to the model by the engine loop.
func (*ScoutTool) Description ¶
func (*ScoutTool) Parameters ¶
type SubAgent ¶
type SubAgent struct {
ID string `json:"id,omitempty"` // optional label for the result
Task string `json:"task"` // the isolated task description
Mode string `json:"mode,omitempty"` // "BUILDER" (default) or "PLANNER" (read-only)
TargetDir string `json:"target_dir,omitempty"` // optional target sub-repository or working directory (e.g. 'services/payment' or 'auth-service')
// Mutates marks a task that may write/delete/execute. Mutating parallel
// agents are never run without explicit user confirmation (see Runner.Ask);
// this keeps fan-out fast and read-only by default but still lets the model
// request a supervised parallel mutation when it is actually useful.
Mutates bool `json:"mutates,omitempty"`
}
SubAgent is a single delegated task.
type SwarmResult ¶
type SwarmResult struct {
Goal string `json:"goal"`
ArchitectSpec string `json:"architect_spec"`
BuilderOutput string `json:"builder_output"`
AuditorVerdict string `json:"auditor_verdict"`
Success bool `json:"success"`
TouchedFiles []string `json:"touched_files,omitempty"`
Duration string `json:"duration"`
Architect RunMetrics `json:"architect_metrics,omitempty"`
Builder RunMetrics `json:"builder_metrics,omitempty"`
Auditor RunMetrics `json:"auditor_metrics,omitempty"`
TotalTokens int `json:"total_tokens"`
TotalCost float64 `json:"total_cost"`
Compactions int `json:"compactions"`
}
SwarmResult contains the combined synthesis from all swarm stages.
func (*SwarmResult) UsageLine ¶ added in v0.1.1
func (s *SwarmResult) UsageLine() string
UsageLine renders a one-line per-phase cost attribution for the swarm completion status (e.g. "arch 1.2k tok / $0.01 · build 9.4k tok / $0.09").
type SwarmTask ¶
type SwarmTask struct {
Goal string `json:"goal"`
Context string `json:"context,omitempty"`
AutoVerify bool `json:"auto_verify,omitempty"`
Timeout time.Duration `json:"timeout,omitempty"`
}
SwarmTask represents a coordinated multi-stage task.
type SwarmTool ¶
type SwarmTool struct {
Runner *Runner
}
SwarmTool exposes the collaborative swarm to the agent loop.
func (*SwarmTool) Description ¶
func (*SwarmTool) Parameters ¶
type Tool ¶
type Tool struct {
Runner *Runner
}
Tool is the native `subagent` tool registered in the main registry. The model calls it to delegate focused work to isolated sub-agents.