Loading...
Loading...
Single-agent recursion and parallel fan-out within one AG2 `Agent` — auto-injected `run_subtask` / `run_subtasks(parallel=True)` (opt in via `tasks=TaskConfig(...)`) for self-delegation, and `Agent.as_tool()` as a lightweight no-hub way to call one named agent from inside another. Use when a single coordinator wants to break work into its own sub-tasks, fan out concurrent sub-tasks, or invoke a specialist agent as a tool. Covers context flow, recursion safety, and `persistent_stream` for sub-task history. **For two or more agents actually collaborating with a registry, durable channels, governance, or turn-taking, use `ag2-network-quickstart` instead** — the network is the standard multi-agent pattern in AG2.
npx skill4agent add ag2ai/ag2-skills ag2-subagent-delegation| Pattern | Reach for it when | API |
|---|---|---|
Auto-injected | Lightweight self-delegation, dynamic fan-out, parallel sub-questions | |
| Distinct named delegates the LLM should reason about ("call the researcher", "call the writer") | Wrap a child Agent as a tool on the parent |
run_subtaskstasks=Falsetasks=TaskConfig(...)run_subtask(task: str)run_subtasks(tasks: list[str], parallel: bool = True)from ag2 import Agent, TaskConfig
from ag2.config import GeminiConfig
config = GeminiConfig(model="gemini-3-flash-preview")
coordinator = Agent(
"coordinator",
prompt=(
"You answer multi-part questions by dispatching run_subtasks "
"with parallel=True. Use one tool call with every sub-question "
"packed into the 'tasks' list."
),
config=config,
tasks=TaskConfig(), # opt in
)
reply = await coordinator.ask(
"In one run_subtasks call, answer: "
"(a) tallest waterfall, (b) Eiffel Tower year, (c) boiling point of nitrogen."
)TaskConfig@dataclass
class TaskConfig:
config: ModelConfig | None = None # falls back to parent's config
prompt: str = "You are a task agent..."
include_tools: Iterable[str] | None = None # None = inherit all parent tools
exclude_tools: Iterable[str] = ()
extra_tools: Iterable[Callable | Tool] = ()TaskConfig(
config=worker_config, # smaller model
prompt="You are a focused worker; one step only.",
include_tools=["search", "fetch_url"], # don't expose `summarize` to children
)tasks=Falserun_subtaskAgent.as_tool()from ag2 import Agent
from ag2.config import AnthropicConfig
config = AnthropicConfig(model="claude-sonnet-4-6")
researcher = Agent("researcher", prompt="Provide concise factual findings.", config=config, tools=[search_tool])
writer = Agent("writer", prompt="Turn research into clear prose.", config=config)
coordinator = Agent(
"coordinator",
prompt="First delegate research, then pass findings to the writer.",
config=config,
tools=[
researcher.as_tool(description="Research a topic and return findings."),
writer.as_tool(description="Write an article. Pass research notes in the context parameter."),
],
)task_researchertask_writerobjectivecontextas_tool()| Parameter | Description |
|---|---|
| Tool description shown to the LLM (required) |
| Override the default |
| |
| |
subagent_tool()from ag2.tools.subagents import subagent_tool
coordinator = Agent("coordinator", config=config, tools=[
subagent_tool(researcher, description="Research a topic."),
])as_tool()sub_taskrun_subtaskanalyst = Agent(
"analyst",
prompt=(
"You have search and sub_task tools. "
"Only use sub_task when the task has clearly independent parts."
),
config=config,
tools=[search_tool],
)
analyst.add_tool(
analyst.as_tool(
description="Break work into a focused sub-task for independent analysis.",
name="sub_task",
)
)as_tool()sub_taskrun_subtaskrun_subtaskstasks=Falserun_subtaskas_tool()context.dependenciessubagentssubagent_toolbackground_agent_toolpersistent_streamStreamFactoryag2.tools.subagentsMemoryStream| What | Behaviour | Why |
|---|---|---|
| Dependencies | Copied (top-level shallow) | Isolated; treat dependencies as read-only inside subtasks |
| Variables | Copied; not synced back to the parent | Concurrent-safe — with siblings running via |
| History | Fresh stream | Clean context; relevant info passes via the |
| Tools | Inherited from parent (filtered by | Sub-tasks need real capabilities to do work |
persistent_stream()from ag2.tools.subagents import persistent_stream
researcher.as_tool(
description="Research a topic",
stream=persistent_stream(),
)context.dependenciesf"ag:{agent.name}:stream"from ag2 import Agent, Context
from ag2.streams.redis import RedisStream
def make_redis_stream(agent: Agent, ctx: Context) -> RedisStream:
return RedisStream(MY_REDIS_URL, prefix=f"ag2:sub:{agent.name}")
researcher.as_tool(description="Research a topic", stream=make_redis_stream)assets/research_squad.pycode_examples/05run_subtasks(parallel=True)Agent.as_tool()TaskStartedTaskCompletedwebsite/docs/user-guide/subagents.mdxtasks=KnowledgeConfigwebsite/docs/user-guide/agent_harness.mdxtasks=FalseTaskConfigrun_subtaskrun_subtasktasks=FalseAgent.as_tool()dependenciesdescription=as_tool()run_subtasks(parallel=False)TrueFalsetask_{agent.name}name=