Nous.Plugins.SubAgent (nous v0.15.4)

View Source

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 via Task.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)

Deps Propagation

By default, no parent deps are forwarded to sub-agents. Sub-agent prompts are LLM-controlled and any tool the sub-agent can call has access to its ctx.deps — so secrets, repos, signed URLs, and tokens placed in the parent's deps would otherwise be one prompt-injected sub-agent task away from exfiltration. Opt in explicitly 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
}

Security note: prior to v0.14.4 (this fix) the default was the equivalent of :all. Upgrading is a behaviour change: if your existing sub-agent flows relied on inheriting parent deps, set sub_agent_shared_deps: :all to restore the old behaviour.