Two complementary multi-Agent patterns in one example. First, a coordinator opts in to the auto-injected run_subtasks tool (via tasks=TaskConfig()) to fan out three independent factual lookups concurrently in a single tool call. Then a second coordinator delegates arithmetic to a math_expert Agent exposed via Agent.as_tool(). Together they show "fan out then collect" alongside "named delegate".
Opting in to run_subtask / run_subtasks via tasks=TaskConfig(...) — disabled by default; subtasks themselves never get them, so recursion is impossible by construction.
Calling run_subtasks(parallel=True) to dispatch many sub-questions concurrently from one tool call.
Wrapping an Agent with Agent.as_tool() to expose it as a named delegate (task_math-expert) on a parent's tool list.
Subscribing to TaskStarted / TaskCompleted lifecycle events to observe the fan-out from outside the Agent.
"""05 · Research squad — parallel subtasks and sibling delegationTwo patterns for multi-Agent orchestration:1. **Opt-in subtask tools.** Pass ``tasks=TaskConfig(...)`` and the Agent gains ``run_subtask`` / ``run_subtasks``. The coordinator uses ``run_subtasks`` with ``parallel=True`` to fan out three short investigations concurrently. Spawned subtasks have **no** ``run_subtask`` tools (they default to ``tasks=False``), so recursion is structurally impossible — no depth limiter needed.2. **``Agent.as_tool()``.** A second Agent (``math_expert``) is exposed to the coordinator as a callable tool. The wrapped Agent has no ``run_subtask`` tools either (default), so recursion is bounded by the call structure.Run:: .venv-beta/bin/python 05_research_squad.py"""importasyncioimporttimefromautogen.betaimportAgentfromautogen.beta.agentimportTaskConfigfromautogen.beta.configimportGeminiConfigfromautogen.beta.eventsimportTaskCompleted,TaskStartedfromautogen.beta.streamimportMemoryStreamdefsection(title:str)->None:print(f"\n── {title} ───")asyncdefmain()->None:config=GeminiConfig(model="gemini-3-flash-preview",temperature=0)section("Parallel subtasks — fan out three lookups in one tool call")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. Be concise."),config=config,tasks=TaskConfig(),# Opt in to run_subtask / run_subtasks.)# Collect subtask lifecycle events so we can show the fan-out to the userstarts:list[TaskStarted]=[]completions:list[TaskCompleted]=[]stream=MemoryStream()stream.where(TaskStarted).subscribe(lambdae:starts.append(e))stream.where(TaskCompleted).subscribe(lambdae:completions.append(e))start=time.monotonic()reply=awaitcoordinator.ask("Use run_subtasks(parallel=True) to answer, in one tool call: ""(a) what is the tallest waterfall in the world, ""(b) what year was the Eiffel Tower completed, ""(c) what is the boiling point of nitrogen in Celsius. ""Then list all three answers.",stream=stream,)elapsed=time.monotonic()-startprint(reply.body)print()print(f"Subtasks dispatched: {len(starts)}")print(f"Subtasks finished: {len(completions)}")print(f"Wall time: {elapsed:.2f}s (3 concurrent LLM calls)")section("Sibling delegation — math_expert is a tool on coordinator2")math_expert=Agent("math-expert",prompt="You are an arithmetic specialist. Reply with only the number.",config=config,)coordinator2=Agent("coordinator2",prompt=("When arithmetic comes up, delegate to the task_math-expert tool ""rather than computing yourself. Then present the answer in a ""complete sentence."),config=config,tools=[math_expert.as_tool(description="Delegate arithmetic problems to the math expert.",)],)reply2=awaitcoordinator2.ask("What is 237 times 19?")print(reply2.body)if__name__=="__main__":asyncio.run(main())