Documentation
¶
Overview ¶
Package subagent — autonomous-execution loop.
AutonomousRunner takes a frozen Contract and drives a child Step interface to completion. It auto-compacts when context fills, watches budget, and hands back a structured FinalReport when the contract is satisfied, exhausted, violated, or handed off.
Package subagent — Contract type and validation/enforcement primitives.
A Contract is the structured handoff between a parent agent and a child sub-agent. The parent freezes it before spawning; the child runs to completion against it without further user/parent intervention. See master plan §5.3 for the autonomous-execution rationale.
Package subagent — contract enforcement at the child's tool boundary.
The enforcer wraps any tool the child uses so that filesystem-mutating calls are checked against contract Scope/OutOfScope before execution. Out-of-scope writes are denied with a ContractViolation and never reach the underlying tool.
Package subagent includes a text-only worker using an OpenAI-compatible API.
Index ¶
- Constants
- Variables
- func DefaultAcceptanceRunner(ctx context.Context, cmd string, timeout time.Duration, workdir string) (int, string, string, error)
- func IsAutoDeny(ctx context.Context) bool
- func NewFileAuditWriter(baseDir, id string) (*fileAuditWriter, error)
- func NewMemAuditWriter() *memAuditWriter
- type AcceptanceCheck
- type AcceptanceResult
- type AcceptanceRunner
- type AcceptanceScanner
- type AgentDef
- type AgentFile
- type AgentPriority
- type AgentRegistry
- func (r *AgentRegistry) FilterByMCPServers(availableServers []string) []AgentDef
- func (r *AgentRegistry) Get(name string) *AgentDef
- func (r *AgentRegistry) List() []AgentDef
- func (r *AgentRegistry) RegisterBuiltin(def AgentDef)
- func (r *AgentRegistry) RegisterCLI(def AgentDef)
- func (r *AgentRegistry) Scan() error
- func (r *AgentRegistry) SelectBest(taskDescription string) *AgentDef
- type AgentRunner
- type AuditEntry
- type AuditWriter
- type AutonomousConfig
- type AutonomousRunner
- type BudgetSnapshot
- type ChildRef
- type CompactionTask
- type Config
- type ContextExport
- type ContextRef
- type ContextRefKind
- type Contract
- type ContractBudget
- type ContractViolation
- type CostRollup
- type Decomposer
- type EnforcedTool
- type ExportContext
- type ExternalDelegator
- func (d *ExternalDelegator) Delegate(ctx context.Context, agentName, goal string) (*Result, error)
- func (d *ExternalDelegator) DelegateWithExport(ctx context.Context, agentName string, export ContextExport) (*Result, error)
- func (d *ExternalDelegator) ListAgents() []AgentDef
- func (d *ExternalDelegator) Register(def AgentDef)
- type FailedAgentFile
- type FileStateTracker
- func (t *FileStateTracker) KnownReads(taskID string) []string
- func (t *FileStateTracker) RecordRead(taskID, path string)
- func (t *FileStateTracker) RecordWrite(taskID, path string)
- func (t *FileStateTracker) WritesByTask(taskID string) []string
- func (t *FileStateTracker) WritesSince(taskID string, since time.Time, knownReads []string) []string
- type FinalReport
- type GenericTask
- type HandoffFailureSink
- type Integration
- type Manager
- func (m *Manager) ActiveChildren() []ChildRef
- func (m *Manager) ActiveCount() int
- func (m *Manager) AutonomousCancel(id string) bool
- func (m *Manager) AutonomousList() []string
- func (m *Manager) AutonomousReport(id string) (report *FinalReport, running bool, err error)
- func (m *Manager) AutonomousStatus(id string) (StatusReport, bool)
- func (m *Manager) AutonomousWait(ctx context.Context, id string) (*FinalReport, error)
- func (m *Manager) CostSummary() RollupSummary
- func (m *Manager) FileState() *FileStateTracker
- func (m *Manager) HasDriverFactory() bool
- func (m *Manager) SetDriverFactory(f func(*Contract) (StepDriver, error))
- func (m *Manager) SetFailureSink(s HandoffFailureSink)
- func (m *Manager) SetRegistry(r *AgentRegistry)
- func (m *Manager) SetRouter(r TaskRouter)
- func (m *Manager) SetWorkerFactory(factory WorkerFactory)
- func (m *Manager) Spawn(ctx context.Context, task Task) (*Result, error)
- func (m *Manager) SpawnBatch(ctx context.Context, tasks []Task) ([]*Result, error)
- func (m *Manager) SpawnBatchAutoSplit(ctx context.Context, tasks []Task) ([]*Result, error)
- func (m *Manager) SpawnContract(ctx context.Context, contract *Contract, driver StepDriver, workdir string, ...) (string, error)
- func (m *Manager) SpawnDecomposed(ctx context.Context, goal, contextStr string) ([]*Result, error)
- func (m *Manager) SpawnFromFactory(ctx context.Context, c *Contract, workdir string) (string, error)
- type ModelHint
- type ModelResolver
- type OnContextFullAction
- type Output
- type OutputKind
- type OutputResult
- type PersonalityUpdateTask
- type Protocol
- type RealWorker
- type RealWorkerConfig
- type Result
- type Role
- type RollupSummary
- type SessionNameTask
- type SpawnConfig
- type StatusReport
- type StepDriver
- type StepResult
- type Task
- type TaskRouter
- type Tool
- type ToolEntry
- type ToolWithPath
- type VisualDebugTask
- type WorkerFactory
- type WorkerRunner
Constants ¶
const XIAOMI_BASE_URL = "https://token-plan-sgp.xiaomimimo.com/v1"
XIAOMI_BASE_URL is the Xiaomi Mimo API endpoint.
Variables ¶
var ErrUnsupportedCapability = errors.New("subagent: unsupported capability")
ErrUnsupportedCapability means a configured child cannot execute a requested tool.
Functions ¶
func DefaultAcceptanceRunner ¶
func DefaultAcceptanceRunner(ctx context.Context, cmd string, timeout time.Duration, workdir string) (int, string, string, error)
DefaultAcceptanceRunner runs the command with `sh -c` in workdir.
WARNING: This executes arbitrary shell commands from AcceptanceCheck.Cmd, which may be LLM-generated or user-authored. Callers should prefer ScannedAcceptanceRunner with a command scanner to block known-dangerous patterns. This raw runner is provided for cases where no scanner is configured.
func IsAutoDeny ¶
IsAutoDeny returns true if the context signals auto-deny for permissions.
func NewFileAuditWriter ¶
NewFileAuditWriter prepares a writer rooted at baseDir/<id>. baseDir is usually ~/.overkill/subagents. Returns nil writer + nil error when the dir can't be created (graceful degradation; auditing is best-effort).
func NewMemAuditWriter ¶
func NewMemAuditWriter() *memAuditWriter
NewMemAuditWriter returns an in-memory audit writer. Useful in tests.
Types ¶
type AcceptanceCheck ¶
type AcceptanceCheck struct {
Name string `json:"name"`
Cmd string `json:"cmd"`
ExpectExit int `json:"expect_exit"`
ExpectStdoutContains string `json:"expect_stdout_contains,omitempty"`
TimeoutSeconds int `json:"timeout_seconds,omitempty"`
}
AcceptanceCheck is a testable command + expectation pair.
type AcceptanceResult ¶
type AcceptanceResult struct {
Name string `json:"name"`
Passed bool `json:"passed"`
ExitCode int `json:"exit_code"`
Stdout string `json:"stdout,omitempty"`
Stderr string `json:"stderr,omitempty"`
Reason string `json:"reason,omitempty"`
}
AcceptanceResult is the outcome of running one AcceptanceCheck.
type AcceptanceRunner ¶
type AcceptanceRunner func(ctx context.Context, cmd string, timeout time.Duration, workdir string) (exitCode int, stdout, stderr string, err error)
AcceptanceRunner is the surface RunAcceptance uses to invoke commands. Defaults to the OS shell; tests inject a fake.
func ScannedAcceptanceRunner ¶
func ScannedAcceptanceRunner(scanner AcceptanceScanner) AcceptanceRunner
ScannedAcceptanceRunner wraps DefaultAcceptanceRunner with a command scanner. When scanner is nil, it delegates to DefaultAcceptanceRunner directly. When a scanner is provided, commands are checked before execution and blocked if the scanner returns blocked=true (B108).
type AcceptanceScanner ¶
AcceptanceScanner is a minimal command-scanning interface. Accept any implementation that has a Scan method returning a blocked boolean and error — no import dependency on internal/security required.
type AgentDef ¶
type AgentDef struct {
Name string
Command string
Args []string
Protocol Protocol
Model string
Env map[string]string
SystemPrompt string // built-in agents only: injected as system prompt
Tools []string // built-in agents only: tool whitelist names
// Claude Code parity fields — all optional.
Description string `yaml:"description,omitempty"` // when to auto-select this agent
DisallowedTools []string `yaml:"disallowedTools,omitempty"` // tools to deny even if inherited
MaxTurns int `yaml:"maxTurns,omitempty"` // max agentic turns before stopping
PermissionMode string `yaml:"permissionMode,omitempty"` // acceptEdits/auto/bypass
Skills []string `yaml:"skills,omitempty"` // skills to preload at startup
Color string `yaml:"color,omitempty"` // UI color for agent identification
Effort string `yaml:"effort,omitempty"` // thinking effort: off/minimal/low/medium/high/x-high
InitialPrompt string `yaml:"initialPrompt,omitempty"` // prepended to first user turn
Background bool `yaml:"background,omitempty"` // always run as background task
Memory string `yaml:"memory,omitempty"` // persistent memory: user/project/local
MCPServers []string `yaml:"mcpServers,omitempty"` // MCP servers scoped to this agent
Hooks []string `yaml:"hooks,omitempty"` // lifecycle hooks for this agent
RequiredMCPServers []string `yaml:"requiredMcpServers,omitempty"` // MCP servers required for agent availability
Filename string `yaml:"-"` // original filename (set at load time)
}
AgentDef describes an external agent that can be delegated work. When Command is empty the agent is a "built-in" — its definition lives in code and is used to configure a sub-agent internally (system prompt, tool whitelist, etc.) rather than spawned as a separate process.
func BuiltinAgents ¶
func BuiltinAgents(resolve ModelResolver) []AgentDef
BuiltinAgents returns the four named built-in agent definitions wired at boot time — Explore, Plan, Verify, and General-purpose. Each agent's Model is resolved at registration time via the provided resolver so Explore gets the cheapest reading model, Verify gets the cheapest tool-capable model, etc.
The resolver is typically a closure over SmartRouter.CheapestModel(). If resolver is nil, all agents use empty model (inherit from caller).
type AgentFile ¶
type AgentFile struct {
Name string `yaml:"name"`
Description string `yaml:"description"`
Tools csvStrings `yaml:"tools,omitempty"`
DisallowedTools csvStrings `yaml:"disallowedTools,omitempty"`
Model string `yaml:"model,omitempty"`
PermissionMode string `yaml:"permissionMode,omitempty"`
MaxTurns int `yaml:"maxTurns,omitempty"`
Skills csvStrings `yaml:"skills,omitempty"`
MCPServers csvStrings `yaml:"mcpServers,omitempty"`
Hooks csvStrings `yaml:"hooks,omitempty"`
Memory string `yaml:"memory,omitempty"` // user/project/local
Color string `yaml:"color,omitempty"`
Effort string `yaml:"effort,omitempty"` // thinking effort level
InitialPrompt string `yaml:"initialPrompt,omitempty"` // prepended to first turn
Background bool `yaml:"background,omitempty"` // always run as background
RequiredMCPServers csvStrings `yaml:"requiredMcpServers,omitempty"` // MCP patterns required
// Body is the markdown after the frontmatter — the system prompt.
Body string `yaml:"-"`
}
AgentFile is the on-disk representation of a sub-agent definition. Mirrors Claude Code's YAML frontmatter + markdown body format. All optional fields match the OpenClaude sub-agent spec exactly.
type AgentPriority ¶
type AgentPriority int
AgentPriority determines which definition wins when multiple share a name. Higher priority (lower number) wins. Mirrors Claude Code's resolution.
const ( PriorityManaged AgentPriority = 1 // organization-wide (managed settings) PriorityCLIFlag AgentPriority = 2 // --agents CLI flag (session only) PriorityProject AgentPriority = 3 // .overkill/agents/ (current project) PriorityUser AgentPriority = 4 // ~/.overkill/agents/ (all projects) PriorityBuiltin AgentPriority = 5 // hardcoded in Go (lowest) )
type AgentRegistry ¶
type AgentRegistry struct {
// FailedFiles tracks files that couldn't be parsed (for diagnostics).
FailedFiles []FailedAgentFile
// contains filtered or unexported fields
}
AgentRegistry discovers, resolves, and manages sub-agent definitions. It implements Claude Code's priority-based resolution: when multiple agents share the same Name, the highest priority (lowest number) wins.
Discovery paths (in priority order, highest first):
- ~/.overkill/agents/managed/ (PriorityManaged)
- .overkill/agents/ (PriorityProject)
- ~/.overkill/agents/ (PriorityUser)
Built-in agents (PriorityBuiltin) are registered programmatically and overridden by any file-based agent with the same name.
func NewAgentRegistry ¶
func NewAgentRegistry(projectDir, userDir string) *AgentRegistry
NewAgentRegistry creates a registry that scans the given directories. projectDir is typically <workdir>/.overkill/agents/. userDir is typically ~/.overkill/agents/.
func (*AgentRegistry) FilterByMCPServers ¶
func (r *AgentRegistry) FilterByMCPServers(availableServers []string) []AgentDef
FilterByMCPServers returns only agents whose RequiredMCPServers are all available. Agents with no requirements always pass. Matches OpenClaude's filterAgentsByMcpRequirements.
func (*AgentRegistry) Get ¶
func (r *AgentRegistry) Get(name string) *AgentDef
Get returns the resolved agent definition for the given name, or nil if no agent is registered.
func (*AgentRegistry) List ¶
func (r *AgentRegistry) List() []AgentDef
List returns all resolved agent definitions, sorted by priority then name.
func (*AgentRegistry) RegisterBuiltin ¶
func (r *AgentRegistry) RegisterBuiltin(def AgentDef)
RegisterBuiltin registers a hardcoded agent at PriorityBuiltin. File-based agents with the same name will override it.
func (*AgentRegistry) RegisterCLI ¶
func (r *AgentRegistry) RegisterCLI(def AgentDef)
RegisterCLI registers a session-only agent from --agents JSON at PriorityCLIFlag. These override everything except managed agents.
func (*AgentRegistry) Scan ¶
func (r *AgentRegistry) Scan() error
Scan discovers agent files recursively in all configured directories and registers them at their respective priority levels. Lower-priority entries for the same name are silently replaced.
func (*AgentRegistry) SelectBest ¶
func (r *AgentRegistry) SelectBest(taskDescription string) *AgentDef
SelectBest finds the agent whose Description best matches the given task description. Returns nil if no agent matches well enough. Simple keyword-overlap scoring for now — embed-based matching can be added later when the embedding bridge is available.
type AgentRunner ¶
type AgentRunner struct {
// contains filtered or unexported fields
}
AgentRunner spawns and manages sub-agents with full OpenClaude parity. Handles: model cascade, permission mode cascade, effort override, slim context for read-only agents, initial prompt injection, and background auto-deny.
func NewAgentRunner ¶
func NewAgentRunner(cfg SpawnConfig) (*AgentRunner, error)
NewAgentRunner creates a runner from a SpawnConfig. Resolves effective model, max steps, and permission mode using OpenClaude's cascade logic.
func (*AgentRunner) AgentID ¶
func (r *AgentRunner) AgentID() string
AgentID returns the unique identifier for this agent run.
func (*AgentRunner) AgentName ¶
func (r *AgentRunner) AgentName() string
AgentName returns the agent definition name.
func (*AgentRunner) Run ¶
func (r *AgentRunner) Run(ctx context.Context) (*Result, error)
Run executes the sub-agent and returns the result. For async agents without permission prompts, auto-deny is active.
func (*AgentRunner) StartedAt ¶
func (r *AgentRunner) StartedAt() time.Time
StartedAt returns when the agent was spawned.
type AuditEntry ¶
type AuditEntry struct {
Timestamp time.Time `json:"ts"`
Tool string `json:"tool"`
Path string `json:"path,omitempty"`
Allowed bool `json:"allowed"`
Reason string `json:"reason,omitempty"`
ArgsLen int `json:"args_len"`
}
AuditEntry is one row of the per-child contract-audit log.
type AuditWriter ¶
type AuditWriter interface {
Write(entry AuditEntry) error
Path() string
}
AuditWriter persists AuditEntry rows. Returns the path it wrote to (if any).
type AutonomousConfig ¶
type AutonomousConfig struct {
Contract *Contract
Driver StepDriver
Workdir string
// Runner overrides AcceptanceRunner; defaults to DefaultAcceptanceRunner.
Runner AcceptanceRunner
// Handoff, if non-nil, receives one StatusReport on handoff/exhaustion.
// Buffered channel recommended (size 1).
Handoff chan StatusReport
}
AutonomousConfig configures an AutonomousRunner.
type AutonomousRunner ¶
type AutonomousRunner struct {
// contains filtered or unexported fields
}
AutonomousRunner drives a StepDriver against a Contract.
func NewAutonomousRunner ¶
func NewAutonomousRunner(cfg AutonomousConfig) (*AutonomousRunner, error)
NewAutonomousRunner constructs a runner. Validates the contract.
func (*AutonomousRunner) Cancel ¶
func (r *AutonomousRunner) Cancel()
Cancel marks the runner as cancelled. Run loop checks on each iteration.
func (*AutonomousRunner) FinalReport ¶
func (r *AutonomousRunner) FinalReport() *FinalReport
FinalReport returns the terminal report once Run has finished. Nil while the runner is still active.
func (*AutonomousRunner) Run ¶
func (r *AutonomousRunner) Run(ctx context.Context) (rep *FinalReport, err error)
Run drives the StepDriver to completion. It NEVER asks the user for input; when the contract cannot be satisfied autonomously it returns a FinalReport describing why.
func (*AutonomousRunner) Status ¶
func (r *AutonomousRunner) Status() StatusReport
Status returns a copy of the current StatusReport.
type BudgetSnapshot ¶
BudgetSnapshot is the runner's view of the child's context budget.
func (BudgetSnapshot) Utilization ¶
func (b BudgetSnapshot) Utilization() float64
Utilization is convenience math for the snapshot.
type ChildRef ¶
type ChildRef struct {
ID string
Goal string
Model string
Status string
StartedAt time.Time
Cancel context.CancelFunc
Result *Result
Depth int
Role Role
}
ChildRef is a live handle to a spawned sub-agent.
type CompactionTask ¶
CompactionTask summarizes conversation history into a concise summary.
func (*CompactionTask) Context ¶
func (t *CompactionTask) Context() string
func (*CompactionTask) Goal ¶
func (t *CompactionTask) Goal() string
func (*CompactionTask) MaxIterations ¶
func (t *CompactionTask) MaxIterations() int
func (*CompactionTask) Model ¶
func (t *CompactionTask) Model() string
func (*CompactionTask) Toolset ¶
func (t *CompactionTask) Toolset() []string
func (*CompactionTask) Validate ¶
func (t *CompactionTask) Validate() error
type Config ¶
type Config struct {
MaxDepth int
MaxChildren int
ChildTimeout time.Duration
CurrentDepth int // fixed parent depth; concurrent children are siblings
// MaxTasksPerChild is the soft limit on how many tasks can be
// dispatched in a single SpawnBatch call. When the input exceeds
// this, SpawnBatchAutoSplit automatically splits into sequential
// batches. Defaults to MaxChildren when unset (0).
MaxTasksPerChild int
}
Config controls the limits and behaviour of a Manager.
type ContextExport ¶
type ContextExport struct {
SessionID string `json:"session_id"`
Goal string `json:"goal"`
Context ExportContext `json:"context"`
OverkillVersion string `json:"overkill_version"`
}
ContextExport is the JSON envelope for cross-agent delegation. It carries session metadata plus the filtered context payload.
func ContextExportFromJSON ¶
func ContextExportFromJSON(data string) (ContextExport, error)
ContextExportFromJSON unmarshals a JSON string into a ContextExport.
func (ContextExport) FilterSecrets ¶
func (e ContextExport) FilterSecrets() ContextExport
FilterSecrets returns a copy of the ContextExport with secrets redacted from all string fields, including top-level Goal and SessionID.
func (ContextExport) ToJSON ¶
func (e ContextExport) ToJSON() (string, error)
ToJSON marshals the ContextExport to a JSON string.
type ContextRef ¶
type ContextRef struct {
Type ContextRefKind `json:"type"`
Value string `json:"value"`
}
ContextRef is one input the parent passes to the child.
type ContextRefKind ¶
type ContextRefKind string
ContextRefKind classifies an Inputs entry the parent passes down.
const ( CtxRefFile ContextRefKind = "file" CtxRefPriorResult ContextRefKind = "prior_result" CtxRefSpec ContextRefKind = "spec" CtxRefNote ContextRefKind = "note" )
type Contract ¶
type Contract struct {
ID string `json:"id"`
ParentSession string `json:"parent_session"`
Goal string `json:"goal"`
Scope []string `json:"scope"`
OutOfScope []string `json:"out_of_scope"`
Inputs []ContextRef `json:"inputs"`
ExpectedOutputs []Output `json:"expected_outputs"`
IntegrationPoints []Integration `json:"integration_points,omitempty"`
Acceptance []AcceptanceCheck `json:"acceptance"`
Budget ContractBudget `json:"budget"`
OnContextFull OnContextFullAction `json:"on_context_full"`
}
Contract is the frozen agreement between parent and child.
func (*Contract) CheckScope ¶
CheckScope reports whether the given filesystem path is allowed for write under this contract. Out-of-scope patterns take precedence over scope. An empty Scope means "no scope restriction" (everything allowed except out_of_scope). If both are empty, all writes are allowed.
func (*Contract) RunAcceptance ¶
func (c *Contract) RunAcceptance(ctx context.Context, workdir string, runner AcceptanceRunner) []AcceptanceResult
RunAcceptance executes every acceptance check against workdir and reports per-check outcomes. Never returns nil; an empty slice means no checks.
type ContractBudget ¶
type ContractBudget struct {
Tokens int `json:"tokens"`
Steps int `json:"steps"`
WallSeconds time.Duration `json:"wall_seconds"`
}
ContractBudget caps a child's resource consumption.
type ContractViolation ¶
type ContractViolation struct {
Criterion string `json:"criterion"`
Reason string `json:"reason"`
Evidence string `json:"evidence,omitempty"`
}
ContractViolation describes a criterion the child failed to satisfy.
func (ContractViolation) Error ¶
func (v ContractViolation) Error() string
type CostRollup ¶
type CostRollup struct {
// contains filtered or unexported fields
}
CostRollup folds child agent token/cost spend into an aggregated total. All methods are safe for concurrent use.
func NewCostRollup ¶
func NewCostRollup(sessionID string) *CostRollup
NewCostRollup creates a new CostRollup associated with the given session.
func (*CostRollup) AddChild ¶
func (c *CostRollup) AddChild(result *Result)
AddChild folds one child's token usage and cost into the rollup. Passing nil is a safe no-op.
func (*CostRollup) Summary ¶
func (c *CostRollup) Summary() RollupSummary
Summary returns a snapshot of the aggregated totals.
type Decomposer ¶
type Decomposer struct {
// contains filtered or unexported fields
}
Decomposer splits a natural-language multi-item goal into discrete tasks. Uses separator patterns and heuristics — no LLM call. When a user dumps "fix X in package A, also wire Y in package B, and then refactor Z" this extracts the individual items so they can be dispatched as parallel sub-agents instead of overwhelming one with a giant context window.
This is intentionally self-contained in the subagent package (no dependency on internal/agent) so it can be called from the delegation path without creating a circular import.
func NewDecomposer ¶
func NewDecomposer() *Decomposer
NewDecomposer returns a Decomposer with sensible defaults.
func (*Decomposer) Decompose ¶
func (d *Decomposer) Decompose(input string) []string
Decompose splits input into discrete task descriptions. Returns nil if fewer than 2 items are found (single-item input doesn't need decomposition).
type EnforcedTool ¶
type EnforcedTool struct {
// contains filtered or unexported fields
}
EnforcedTool wraps a Tool and gates its Execute call through a Contract.
func NewEnforcedTool ¶
func NewEnforcedTool(inner Tool, contract *Contract, audit AuditWriter, violCh chan<- ContractViolation) *EnforcedTool
NewEnforcedTool wraps inner with contract enforcement. violCh, if non-nil, receives every denied call (best-effort, non-blocking).
func (*EnforcedTool) Execute ¶
func (e *EnforcedTool) Execute(ctx context.Context, input json.RawMessage) (json.RawMessage, error)
func (*EnforcedTool) Name ¶
func (e *EnforcedTool) Name() string
type ExportContext ¶
type ExportContext struct {
FilesModified []string `json:"files_modified,omitempty"`
RecentChanges string `json:"recent_changes,omitempty"`
ProjectStructure string `json:"project_structure,omitempty"`
Constraints string `json:"constraints,omitempty"`
Language string `json:"language,omitempty"`
RelatedConversation string `json:"related_conversation,omitempty"`
}
ExportContext holds the structured context passed between agents during delegation.
type ExternalDelegator ¶
type ExternalDelegator struct {
// Registry, when set, provides file-based agent discovery and
// auto-selection via SelectBest. Populated at boot time.
Registry *AgentRegistry
// contains filtered or unexported fields
}
ExternalDelegator manages registration and delegation of tasks to external agent processes. All public methods are safe for concurrent use.
func NewExternalDelegator ¶
func NewExternalDelegator(workDir string, timeout time.Duration, fileState *FileStateTracker) *ExternalDelegator
NewExternalDelegator creates a delegator that runs external agents in workDir with the given default timeout. If fileState is nil, a new tracker is created.
func (*ExternalDelegator) Delegate ¶
Delegate sends a goal to the named external agent. If agentName is empty and a Registry is configured, SelectBest is used for auto-selection. It is a convenience wrapper around DelegateWithExport using a minimal ContextExport.
func (*ExternalDelegator) DelegateWithExport ¶
func (d *ExternalDelegator) DelegateWithExport(ctx context.Context, agentName string, export ContextExport) (*Result, error)
DelegateWithExport sends a filtered ContextExport to the named external agent process, waits for it to finish (or timeout), and returns the result.
Steps:
- Look up agent by name → error if not found
- exec.LookPath(agent.Command) → error if not in PATH
- Call export.FilterSecrets() then export.ToJSON()
- Create context with timeout
- Build exec.CommandContext(ctx, agent.Command, append(agent.Args, inputData)...)
- Set cmd.Dir to workDir
- Capture stdout/stderr via bytes.Buffer
- Run command
- On error: check ctx.Err() for DeadlineExceeded → "timeout", Canceled → "interrupted", else "failed"
- Return Result with Summary=stdout, status/exitReason set accordingly
func (*ExternalDelegator) ListAgents ¶
func (d *ExternalDelegator) ListAgents() []AgentDef
ListAgents returns all registered agent definitions in an indeterminate order. When a Registry is configured, it returns the registry's resolved list (which includes file-based, built-in, and CLI agents).
func (*ExternalDelegator) Register ¶
func (d *ExternalDelegator) Register(def AgentDef)
Register adds an external agent definition. If an agent with the same name already exists it is replaced.
type FailedAgentFile ¶
FailedAgentFile records a file that looked like an agent definition but couldn't be parsed. Matches OpenClaude's failedFiles pattern.
type FileStateTracker ¶
type FileStateTracker struct {
// contains filtered or unexported fields
}
FileStateTracker tracks which files each task (agent) reads and writes. It detects conflicts when a child agent modifies files the parent previously read. All methods are safe for concurrent use by multiple goroutines.
func NewFileStateTracker ¶
func NewFileStateTracker() *FileStateTracker
NewFileStateTracker creates a new, ready-to-use FileStateTracker.
func (*FileStateTracker) KnownReads ¶
func (t *FileStateTracker) KnownReads(taskID string) []string
KnownReads returns a copy of all normalized file paths that taskID has read. Returns an empty (non-nil) slice for unknown tasks.
func (*FileStateTracker) RecordRead ¶
func (t *FileStateTracker) RecordRead(taskID, path string)
RecordRead records that taskID read the file at path. The path is normalized to an absolute path via filepath.Abs.
func (*FileStateTracker) RecordWrite ¶
func (t *FileStateTracker) RecordWrite(taskID, path string)
RecordWrite records that taskID wrote to the file at path. The path is normalized to an absolute path via filepath.Abs.
func (*FileStateTracker) WritesByTask ¶
func (t *FileStateTracker) WritesByTask(taskID string) []string
WritesByTask returns a copy of all normalized file paths that taskID has written to. Returns an empty (non-nil) slice for unknown tasks.
func (*FileStateTracker) WritesSince ¶
func (t *FileStateTracker) WritesSince(taskID string, since time.Time, knownReads []string) []string
WritesSince returns the intersection of knownReads and the files written by taskID since the given time. This detects conflicts: files that the parent read and the child wrote. Pass time.Time{} (zero value) to include all writes regardless of timestamp.
type FinalReport ¶
type FinalReport struct {
ContractID string `json:"contract_id"`
Status string `json:"status"` // completed | violated | exhausted | handed_off | failed
Outputs []OutputResult `json:"outputs"`
Acceptance []AcceptanceResult `json:"acceptance"`
Violations []ContractViolation `json:"violations,omitempty"`
TokensUsed int `json:"tokens_used"`
StepsUsed int `json:"steps_used"`
Elapsed time.Duration `json:"elapsed"`
Reason string `json:"reason,omitempty"`
LastOutput string `json:"last_output,omitempty"`
}
FinalReport is the terminal outcome of a Run.
type GenericTask ¶
type GenericTask struct {
GoalStr string
ContextStr string
ToolsetVal []string
ModelVal string
MaxStepsVal int
}
GenericTask is a general-purpose task that satisfies the Task interface. It is used by the delegate_task tool to spawn arbitrary sub-agent work.
func (GenericTask) Context ¶
func (t GenericTask) Context() string
func (GenericTask) Goal ¶
func (t GenericTask) Goal() string
func (GenericTask) MaxIterations ¶
func (t GenericTask) MaxIterations() int
func (GenericTask) Model ¶
func (t GenericTask) Model() string
func (GenericTask) Toolset ¶
func (t GenericTask) Toolset() []string
func (GenericTask) Validate ¶
func (t GenericTask) Validate() error
type HandoffFailureSink ¶
type HandoffFailureSink interface {
OnDelegationFailure(parentSession string, contract *Contract, report *FinalReport, err error)
}
HandoffFailureSink receives a structured record of every cross-agent failure so the parent's journal can attribute the fault to the delegation decision, not just to the child.
type Integration ¶
type Integration struct {
Description string `json:"description"`
Reference string `json:"reference,omitempty"`
}
Integration captures an interface the child's output must conform to.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager coordinates sub-agent spawning with depth/capacity limits and parallel execution. All public methods are safe for concurrent use.
func NewManager ¶
NewManager creates a Manager with sensible defaults.
Defaults: MaxDepth=2, MaxChildren=3, ChildTimeout=120s (when <= 0).
func (*Manager) ActiveChildren ¶
ActiveChildren returns a snapshot of currently running children. Safe for concurrent use; the returned slice is owned by the caller.
func (*Manager) ActiveCount ¶
ActiveCount returns the number of currently running children (Spawn path).
func (*Manager) AutonomousCancel ¶
AutonomousCancel signals the child runner to stop and unblocks AutonomousWait. Returns false when no such child exists.
func (*Manager) AutonomousList ¶
AutonomousList returns the IDs of all registered contract-driven children.
func (*Manager) AutonomousReport ¶
func (m *Manager) AutonomousReport(id string) (report *FinalReport, running bool, err error)
AutonomousReport returns the FinalReport once the child has finished. When running is true, the child is still in flight.
func (*Manager) AutonomousStatus ¶
func (m *Manager) AutonomousStatus(id string) (StatusReport, bool)
AutonomousStatus returns the live status of a contract-driven child. The boolean is false when no such child exists.
func (*Manager) AutonomousWait ¶
AutonomousWait blocks until the child finishes, or ctx is cancelled.
func (*Manager) CostSummary ¶
func (m *Manager) CostSummary() RollupSummary
CostSummary returns a snapshot of the aggregated child costs.
func (*Manager) FileState ¶
func (m *Manager) FileState() *FileStateTracker
FileState returns the manager's file-state tracker.
func (*Manager) HasDriverFactory ¶
HasDriverFactory reports whether a factory has been configured.
func (*Manager) SetDriverFactory ¶
func (m *Manager) SetDriverFactory(f func(*Contract) (StepDriver, error))
SetDriverFactory wires a per-contract StepDriver builder. cmd/overkill calls this once at startup with a closure that constructs a clean child agent.
func (*Manager) SetFailureSink ¶
func (m *Manager) SetFailureSink(s HandoffFailureSink)
SetFailureSink wires a delegation-failure observer (master plan §5.3). Pass nil to clear.
func (*Manager) SetRegistry ¶
func (m *Manager) SetRegistry(r *AgentRegistry)
SetRegistry wires an agent registry for file-based agent discovery and auto-selection. Pass nil to clear.
func (*Manager) SetRouter ¶
func (m *Manager) SetRouter(r TaskRouter)
SetRouter wires a task-level model router. Pass nil to clear.
func (*Manager) SetWorkerFactory ¶
func (m *Manager) SetWorkerFactory(factory WorkerFactory)
SetWorkerFactory overrides worker construction. Passing nil restores the production text-only worker. Tool-capable delegation uses SetDriverFactory.
func (*Manager) Spawn ¶
Spawn executes a single task. Initialization and execution failures return a failed Result and a non-nil error; no simulated work runs in production.
func (*Manager) SpawnBatch ¶
SpawnBatch validates all tasks before dispatch and reserves capacity for the whole batch. Independent siblings finish even if one fails. Results retain their input indices; the returned error joins every indexed child failure.
func (*Manager) SpawnBatchAutoSplit ¶
SpawnBatchAutoSplit is like SpawnBatch but automatically splits oversized task lists into sequential batches. When len(tasks) > batchSize(), tasks are sliced into batches of batchSize(), each run via SpawnBatch in order, and results are concatenated. This prevents single sub-agents from hitting max_iterations when the parent dumps 9+ tasks on them.
func (*Manager) SpawnContract ¶
func (m *Manager) SpawnContract(ctx context.Context, contract *Contract, driver StepDriver, workdir string, runner AcceptanceRunner) (string, error)
SpawnContract registers a contract-driven autonomous child and runs it in a background goroutine. Returns the contract ID immediately; the parent calls Status / Wait / Cancel against that ID.
Workdir, if non-empty, is the working directory passed to AcceptanceRunner. Runner overrides the default acceptance runner (useful in tests).
func (*Manager) SpawnDecomposed ¶
SpawnDecomposed handles a single goal string that may contain multiple independent items. It decomposes the goal via Decomposer — if 2+ items are found, they're dispatched as parallel sub-agents through SpawnBatchAutoSplit. If only one item (or decomposition fails), it falls back to a normal single-task Spawn.
This is the smart delegation path: instead of dumping "fix X in package A, also wire Y in package B, and refactor Z" onto one overwhelmed sub-agent, the Decomposer splits it into 3 discrete tasks that run in parallel.
type ModelHint ¶
ModelHint describes the capabilities a built-in agent needs. Used by BuiltinAgents to resolve the cheapest capable model via the router.
type ModelResolver ¶
ModelResolver returns a model ID and provider for the given hint. The router implementation picks the cheapest model matching the capabilities.
type OnContextFullAction ¶
type OnContextFullAction string
OnContextFullAction tells the autonomous runner what to do when its child's context budget approaches the configured cap.
const ( OnContextFullCompactAndContinue OnContextFullAction = "compact_and_continue" OnContextFullHandoffToParent OnContextFullAction = "handoff_to_parent" OnContextFullFail OnContextFullAction = "fail" )
type Output ¶
type Output struct {
Kind OutputKind `json:"kind"`
Spec string `json:"spec"`
}
Output is one concrete deliverable the child must produce.
type OutputKind ¶
type OutputKind string
OutputKind classifies an ExpectedOutputs entry.
const ( OutFile OutputKind = "file" OutSymbol OutputKind = "symbol" OutBehavior OutputKind = "behavior" OutTest OutputKind = "test" )
type OutputResult ¶
type OutputResult struct {
Spec string `json:"spec"`
Kind string `json:"kind"`
Satisfied bool `json:"satisfied"`
}
OutputResult is the per-ExpectedOutput verdict.
type PersonalityUpdateTask ¶
type PersonalityUpdateTask struct {
SessionMessages []providers.Message
CurrentLevel personality.Level
AgentName string
}
PersonalityUpdateTask analyzes conversation for relationship milestones.
func (*PersonalityUpdateTask) Context ¶
func (t *PersonalityUpdateTask) Context() string
func (*PersonalityUpdateTask) Goal ¶
func (t *PersonalityUpdateTask) Goal() string
func (*PersonalityUpdateTask) MaxIterations ¶
func (t *PersonalityUpdateTask) MaxIterations() int
func (*PersonalityUpdateTask) Model ¶
func (t *PersonalityUpdateTask) Model() string
func (*PersonalityUpdateTask) Toolset ¶
func (t *PersonalityUpdateTask) Toolset() []string
func (*PersonalityUpdateTask) Validate ¶
func (t *PersonalityUpdateTask) Validate() error
type Protocol ¶
type Protocol int
Protocol determines how the host communicates with an external agent process.
type RealWorker ¶
type RealWorker struct {
// contains filtered or unexported fields
}
RealWorker performs one text-only completion from the supplied context. It cannot inspect the workspace or execute tools; those tasks require a contract StepDriver configured by the application.
func NewRealWorker ¶
func NewRealWorker(cfg RealWorkerConfig) (*RealWorker, error)
NewRealWorker creates a RealWorker using the available API key for the provider. Falls back to XIAOMI_API_KEY for "xiaomi"; supports DEEPSEEK_API_KEY for "deepseek". Returns an error when no key is available for the requested provider.
type RealWorkerConfig ¶
type RealWorkerConfig struct {
Tools []string // explicit tool capabilities requested by this task
Goal string
Context string
MaxSteps int
Timeout time.Duration
Model string // from SmartRouter.Route().ModelID or fallback "mimo-v2-pro"
Provider string // from SmartRouter.Route().Provider or fallback "xiaomi"
TaskIndex int // index assigned by the manager for result tracking
MaxTokens int // completion limit override; 0 uses model/provider default
}
RealWorkerConfig configures a real LLM-backed worker.
type Result ¶
type Result struct {
TaskIndex int `json:"task_index"`
Status string `json:"status"`
Summary string `json:"summary"`
Error string `json:"error,omitempty"`
TokensIn int64 `json:"tokens_in"`
TokensOut int64 `json:"tokens_out"`
CostUSD float64 `json:"cost_usd"`
DurationMs int64 `json:"duration_ms"`
ToolTrace []ToolEntry `json:"tool_trace,omitempty"`
FilesRead []string `json:"files_read,omitempty"`
FilesWritten []string `json:"files_written,omitempty"`
ExitReason string `json:"exit_reason"`
}
Result captures the outcome of a single sub-agent task execution. This is the authoritative definition — cost.go references it.
type RollupSummary ¶
RollupSummary is a point-in-time snapshot of aggregated child agent costs.
type SessionNameTask ¶
SessionNameTask generates a concise session title from the first message.
func (*SessionNameTask) Context ¶
func (t *SessionNameTask) Context() string
func (*SessionNameTask) Goal ¶
func (t *SessionNameTask) Goal() string
func (*SessionNameTask) MaxIterations ¶
func (t *SessionNameTask) MaxIterations() int
func (*SessionNameTask) Model ¶
func (t *SessionNameTask) Model() string
func (*SessionNameTask) Toolset ¶
func (t *SessionNameTask) Toolset() []string
func (*SessionNameTask) Validate ¶
func (t *SessionNameTask) Validate() error
type SpawnConfig ¶
type SpawnConfig struct {
// Agent definition (from registry or built-in).
Agent AgentDef
// Prompt messages — the goal/context for this agent run.
Goal string
Context string
// Whether this is an async/background agent. Async agents
// auto-deny permission prompts since there's no UI.
IsAsync bool
// When true, the agent CAN show permission prompts even if async.
CanShowPermissionPrompts bool
// Forked context from the parent conversation.
ForkContext string
// Model override from the caller.
ModelOverride string
ProviderOverride string
// Max turns/steps override.
MaxStepsOverride int
// Max tokens override.
MaxTokensOverride int
// Timeout override.
TimeoutOverride time.Duration
// Tool whitelist for this agent session (agent.Tools if empty).
AllowedTools []string
// Worktree path if agent has isolation: "worktree".
WorktreePath string
// Parent agent ID for hierarchy tracking.
ParentAgentID string
// Task index for result tracking.
TaskIndex int
}
SpawnConfig holds all parameters for spawning a sub-agent with full Claude Code / OpenClaude parity. Every field that OpenClaude's runAgent accepts is represented here.
type StatusReport ¶
type StatusReport struct {
ContractID string `json:"contract_id"`
Done []string `json:"done"`
Pending []string `json:"pending"`
Violations []ContractViolation `json:"violations,omitempty"`
TokensUsed int `json:"tokens_used"`
StepsUsed int `json:"steps_used"`
Elapsed time.Duration `json:"elapsed"`
NextRecommendedAction string `json:"next_recommended_action"`
}
StatusReport is a mid-flight snapshot of the runner.
type StepDriver ¶
type StepDriver interface {
// Step performs exactly one unit of work. Implementations should not
// loop internally — the runner owns the iteration.
Step(ctx context.Context) StepResult
// Budget returns a current snapshot of token usage.
Budget() BudgetSnapshot
// Compact attempts to reduce context to fit. Implementations should
// return the post-compaction BudgetSnapshot.
Compact(ctx context.Context) (BudgetSnapshot, error)
// CheckOutput returns the list of ExpectedOutputs (by Spec) that have
// been satisfied so far. Implementations may use simple file-existence
// checks for OutFile, or model-side heuristics for other kinds.
CheckOutput(ctx context.Context, outputs []Output) (satisfiedSpecs []string)
}
StepDriver is the small interface AutonomousRunner consumes. Real agents (internal/agent.Agent) adapt to this via a thin shim; tests provide fakes.
type StepResult ¶
type StepResult struct {
// ToolCalls executed during the step (used for step counting).
ToolCalls int
// Tokens used (cumulative or delta — runner only inspects the
// CurrentTokens snapshot from BudgetSnapshot).
Tokens int
// Done is true when the underlying agent reports task completion (e.g. a
// final assistant turn with no further tool calls).
Done bool
// Output is the assistant text produced this step (last seen).
Output string
// Err, if non-nil, is a per-step error. Tool-level ContractViolations
// should be returned as an error implementing the violation interface
// so the runner can surface them in FinalReport.Violations.
Err error
}
StepResult is the agent-agnostic outcome of one driver step.
type Task ¶
type Task interface {
Goal() string
Context() string
Toolset() []string
Model() string
MaxIterations() int
Validate() error
}
Task is the interface every sub-agent task must implement.
type TaskRouter ¶
type TaskRouter interface {
RouteTask(ctx context.Context, goal, contextStr string) (modelID, provider string, ok bool)
}
TaskRouter picks a model for a sub-agent task. Satisfied by *routing.SmartRouter via a thin adapter at the wiring site. Lives here (not in routing) to avoid import cycles:
agent → subagent → routing → agent ✗
type Tool ¶
type Tool interface {
Name() string
Execute(ctx context.Context, input json.RawMessage) (json.RawMessage, error)
}
Tool is the minimal tool surface the enforcer wraps. Defined locally to avoid an import cycle with internal/tools (which already depends on this package via the delegate tool).
type ToolEntry ¶
type ToolEntry struct {
Tool string `json:"tool"`
ArgsLen int `json:"args_len"`
Path string `json:"path,omitempty"`
Success bool `json:"success"`
Error string `json:"error,omitempty"`
InputHash string `json:"input_hash,omitempty"`
OutputHash string `json:"output_hash,omitempty"`
}
ToolEntry records a single tool invocation during task execution.
type ToolWithPath ¶
type ToolWithPath interface {
IntendedPath(input json.RawMessage) string
}
ToolWithPath is a small interface that, if implemented by a Tool, lets the enforcer skip the JSON-decode dance and ask the tool directly which path it intends to mutate. Optional — most tools won't implement it.
type VisualDebugTask ¶
VisualDebugTask compares two screenshots and reports visual differences.
func (*VisualDebugTask) Context ¶
func (t *VisualDebugTask) Context() string
func (*VisualDebugTask) Goal ¶
func (t *VisualDebugTask) Goal() string
func (*VisualDebugTask) MaxIterations ¶
func (t *VisualDebugTask) MaxIterations() int
func (*VisualDebugTask) Model ¶
func (t *VisualDebugTask) Model() string
func (*VisualDebugTask) Toolset ¶
func (t *VisualDebugTask) Toolset() []string
func (*VisualDebugTask) Validate ¶
func (t *VisualDebugTask) Validate() error
type WorkerFactory ¶
type WorkerFactory func(RealWorkerConfig) (WorkerRunner, error)
WorkerFactory builds a fresh runner for each task. Supplying a factory is an explicit dependency override; provider failures never select another runner.