Plugin that enables agents to delegate tasks to specialized sub-agents.
Provides two tools:
delegate_task— run a single sub-agent for one task (sequential)spawn_agents— run multiple sub-agents in parallel viaTask.Supervisor
Usage
agent = Agent.new("openai:gpt-4",
plugins: [Nous.Plugins.SubAgent],
deps: %{
sub_agent_templates: %{
"researcher" => Agent.new("openai:gpt-4o-mini",
instructions: "You are a research specialist. Find accurate information."
),
"coder" => Agent.new("openai:gpt-4",
instructions: "You are a coding specialist. Write clean Elixir code."
)
}
}
)Templates
Pre-configured agent templates can be provided via deps[:sub_agent_templates].
Templates can be either %Nous.Agent{} structs or config maps:
# Using Agent structs (recommended)
"researcher" => Agent.new("openai:gpt-4o-mini", instructions: "Research specialist")
# Using config maps (legacy)
"researcher" => %{model: "openai:gpt-4o-mini", instructions: "Research specialist"}Both delegate_task and spawn_agents can reference templates by name or
provide inline model/instructions for ad-hoc sub-agents.
Parallel Configuration
Configure concurrency and timeout for spawn_agents via deps:
:parallel_max_concurrency— max concurrent sub-agents (default: 5):parallel_timeout— per-task timeout in ms (default: 120_000)
Bounds on what the model may spawn
The tool arguments are LLM-controlled, so three limits bound them. All three
are read from deps, inherit across delegation like confinement (a nested
sub-agent cannot loosen them), and refuse rather than silently adjust:
:sub_agent_allowed_models— model strings an inlinemodelargument may name (templates are developer-configured and are not checked). Default: the parent agent's own model only. A model outside the list is rejected with a tool error, never substituted.:sub_agent_max_tasks— most tasks onespawn_agentscall may carry (default: 10). An over-cap call is rejected whole, not truncated.:sub_agent_max_depth— how deep delegation may nest (default: 2: the root agent may delegate, its sub-agent may delegate once more, and that sub-sub-agent may not). The current depth travels as:sub_agent_depth.
Deps Propagation
Two different things travel from parent to sub-agent, with opposite defaults:
Data deps (database handles, API keys, signed URLs, ...) are forwarded
ONLY on explicit opt-in. Sub-agent prompts are LLM-controlled and any tool
the sub-agent can call has access to its ctx.deps — so secrets placed in
the parent's deps would otherwise be one prompt-injected sub-agent task away
from exfiltration. Opt in by listing the keys to share, or request
"everything except plugin internals" via the :all shortcut:
deps: %{
sub_agent_templates: %{...},
database: MyApp.Repo,
api_key: "sk-...",
# Pick one:
sub_agent_shared_deps: [:database] # share only :database
# sub_agent_shared_deps: :all # share everything except internals
}Confinement and execution policy ALWAYS inherit, regardless of
:sub_agent_shared_deps: the parent's :workspace_root and :session_id
deps, its effective sandbox policy, its permission policy, and its approval
handler all travel to every sub-agent. Withholding them would not protect a
secret — it would silently widen what a delegated agent may do (e.g.
re-rooting PathGuard at File.cwd!() or dropping the approval gate). A
sub-agent template may narrow the inherited sandbox/permissions, never
widen them.
Two boundaries of that inheritance to know about: hooks do not inherit —
a sub-agent runs only the hooks its own template declares, so an operator's
:pre_tool_use guard on the parent does not gate delegated tool calls (deny
tools via :permissions, which does inherit, when that matters). And a
parent with no policy at all (sandbox/permissions unset, no approval
handler) delegates the same unbounded capability set it has itself —
inheritance bounds sub-agents by the parent's policy, it does not invent one.
Security note: prior to v0.14.4 the default was the equivalent of
:all. Upgrading is a behaviour change: if your existing sub-agent flows relied on inheriting parent deps, setsub_agent_shared_deps: :allto restore the old behaviour.