Documentation
¶
Overview ¶
Package agentreg provides subagent infrastructure for jungi.
A subagent is an independent session with its own context window, model, and system prompt. It shares the parent session's sandbox but maintains separate conversation state, logging, and usage tracking. When a subagent completes its task, only its final text response and accumulated costs are folded back into the parent session.
Storage, merge, frontmatter splitting, and directory loading are shared with promptreg and skillreg via internal/core/mdreg; this package supplies only the Definition value type, its YAML frontmatter shape, and an AGENT.md subdir directory layout.
Index ¶
- func LoadFromFS(fsys fs.FS, dir string) (*Registry, []LoadWarning, error)
- func LoadRegistry(dir string) (*Registry, []LoadWarning, error)
- func MergeRegistries(regs ...*Registry) (*Registry, []LoadWarning)
- func NewID() (string, error)
- type Definition
- type LoadWarning
- type ParallelError
- type ParallelResult
- type ParallelTask
- type ProgressEvent
- type Registry
- type RunResult
- type Runner
- func (r *Runner) Agents() *Registry
- func (r *Runner) GetAgent(name string) (Definition, bool)
- func (r *Runner) Run(ctx context.Context, def Definition, instructions string, agentID string) (RunResult, error)
- func (r *Runner) RunParallel(ctx context.Context, tasks []ParallelTask, onProgress func(ProgressEvent)) ParallelResult
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func LoadFromFS ¶
LoadFromFS reads agent definitions from an fs.FS-rooted tree. dir is the directory inside the FS whose immediate children are treated as agent directories, each containing an AGENT.md file with YAML frontmatter.
Invalid files produce a LoadWarning and are skipped without aborting the load. A non-existent dir is not an error — the Registry is empty.
func LoadRegistry ¶
func LoadRegistry(dir string) (*Registry, []LoadWarning, error)
LoadRegistry scans dir for agent subdirectories and returns a Registry plus any warnings about skipped entries.
Each direct subdirectory of dir containing an AGENT.md file is treated as an agent directory. Subdirectories with valid frontmatter (required name and description fields) are registered under the name given in the frontmatter. Invalid entries — missing AGENT.md, missing fences, malformed YAML, missing required fields, invalid names, or duplicate names — produce a LoadWarning and are skipped without aborting the load. Symlinks are skipped with a warning regardless of their target.
A non-existent dir is not an error: the returned Registry is empty and no warnings are generated. Other I/O errors (permissions, etc.) are returned.
func MergeRegistries ¶
func MergeRegistries(regs ...*Registry) (*Registry, []LoadWarning)
MergeRegistries returns a new Registry combining definitions from each input in order, with first-wins semantics on name collision. nil registries are tolerated and treated as empty.
func NewID ¶ added in v0.2.0
NewID generates a 6-character hex string for agent instance identification. It is the canonical agent-instance ID generator: callers that need to reference an agent before Run starts (e.g. to emit a start event) call this themselves and pass the resulting ID to Run.
Types ¶
type Definition ¶
Definition describes a subagent's identity and configuration.
The Body field serves as the subagent's system prompt. It is the equivalent of the markdown body in a Claude Code agent file.
Tools is the optional list of tool names the agent is permitted to use. An empty slice means the caller decides which tools to enable.
type LoadWarning ¶
LoadWarning describes an AGENT.md file that was skipped during registry construction. Warnings are returned alongside the registry so callers can surface them without the agent package taking a logger dependency.
type ParallelError ¶
ParallelError captures a single agent failure during parallel execution. Err is always non-nil: ParallelError is only ever constructed in the error branch of the parallel run loop below, where err is known non-nil.
type ParallelResult ¶
type ParallelResult struct {
Results []RunResult
Errors []ParallelError
}
ParallelResult holds results and errors from concurrent agent execution.
type ParallelTask ¶
type ParallelTask struct {
Def Definition
Instructions string
}
ParallelTask pairs a definition with its instructions for batch execution.
type ProgressEvent ¶
type ProgressEvent struct {
AgentID string
AgentName string
Started bool // true for start events
Result *RunResult // non-nil on successful completion
Error *ParallelError // non-nil on failure
}
ProgressEvent is sent when an agent starts or finishes during parallel execution.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry holds the set of agent definitions available for the lifetime of a session. It is built once at startup; subsequent filesystem changes are ignored.
func EmptyRegistry ¶
func EmptyRegistry() *Registry
EmptyRegistry returns a Registry with no agents. Use it when no agents directory is present, so callers avoid nil checks.
func MustLoadEmbedded ¶
MustLoadEmbedded loads agent definitions from an embedded fs.FS via LoadFromFS and panics on any load error or warning. Meant for jungi's bundled agent package (internal/agents) whose //go:embed'd files are static: any failure to parse them is a build defect, not a runtime condition.
func (*Registry) Get ¶
func (r *Registry) Get(name string) (Definition, bool)
Get returns the Definition for the named agent and a boolean indicating whether it was found.
func (*Registry) List ¶
func (r *Registry) List() []Definition
List returns the registered agent definitions in load order. The returned slice is freshly allocated and safe to mutate.
type RunResult ¶
type RunResult struct {
AgentID string
AgentName string
Content string
Usage usage.SessionUsage
Events []toolexec.ToolEvent
}
RunResult holds the outcome of a subagent execution.
type Runner ¶
type Runner struct {
// ClientFactory overrides client construction for testing. Production
// (newDefaultAgentClient) resolves each agent's credential from its own
// model's provider, so a test factory need not receive an API key at
// all — doing so previously let injected factories mask cross-provider
// misrouting. If nil, newDefaultAgentClient is used.
ClientFactory func(log *logger.Logger, prompt string, m model.ID, tools []tooldef.Definition) client.Client
// contains filtered or unexported fields
}
Runner holds the shared dependencies needed to launch subagents. It is constructed once and reused across agent invocations within a parent session.
func NewRunner ¶
func NewRunner(sb sandbox.Sandbox, logDir, parentSessionID string, skills *skillreg.Registry, agents *Registry, lspMgr *corelsp.Manager) *Runner
NewRunner creates a Runner bound to the parent session's sandbox and log directory. The parentSessionID is used to name agent log files for correlation.
Each subagent's credential is resolved from its own model's provider at client-construction time (see newDefaultAgentClient), so NewRunner takes no credential of its own.
skills is the registry threaded into each subagent's executor and system prompt. It may be nil; in that case subagents see no skills.
agents is the registry of agent definitions the runner can look up by name. It may be nil; callers that always pass a Definition directly can omit it.
lspMgr is the parent session's language-server manager. Subagents share it read-only (diagnostics/hover/references); Manager is concurrency-safe. May be nil or disabled — subagents simply omit the lsp tool in that case.
func (*Runner) Agents ¶
Agents returns the runner's agent registry, which may be nil if the runner was constructed without one.
func (*Runner) GetAgent ¶
func (r *Runner) GetAgent(name string) (Definition, bool)
GetAgent looks up a named agent definition from the runner's registry. Returns the Definition and true if found, zero value and false otherwise. Callers that always construct a Definition themselves may ignore this.
func (*Runner) Run ¶
func (r *Runner) Run(ctx context.Context, def Definition, instructions string, agentID string) (RunResult, error)
Run executes a subagent with the given instructions in an independent session. It creates its own client, executor, and logger, runs the instruction through the agent's tool loop, and returns the result.
The agentID parameter identifies this agent instance. If empty, a random ID is generated.
The parent's sandbox is shared (same working directory restrictions). All other state—conversation history, token usage, log file—is isolated.
func (*Runner) RunParallel ¶
func (r *Runner) RunParallel(ctx context.Context, tasks []ParallelTask, onProgress func(ProgressEvent)) ParallelResult
RunParallel executes multiple agents concurrently and collects results. It always waits for all agents to finish. Successful results and errors are collected separately; partial success is not treated as failure.
If onProgress is non-nil, it is called each time an individual agent completes (success or failure), enabling progressive UI updates.
Source Files
¶
- definition.go
- registry.go
- runner.go