Basic Usage¶
Using SubAgentCapability (Recommended)¶
The simplest way to add subagent delegation:
import asyncio
from pydantic_ai import Agent
from subagents_pydantic_ai import SubAgentCapability, SubAgentConfig
agent = Agent(
"openai:gpt-4.1",
capabilities=[SubAgentCapability(
subagents=[
SubAgentConfig(
name="researcher",
description="Researches topics and gathers information",
instructions="You are a research assistant. Investigate thoroughly.",
),
SubAgentConfig(
name="summarizer",
description="Summarizes long content into concise points",
instructions="You are a summarization expert. Be concise.",
),
],
)],
)
async def main():
result = await agent.run("Research the benefits of async programming in Python")
print(result.output)
asyncio.run(main())
SubAgentCapability handles everything:
- Registers
task,check_task,answer_subagent, and management tools - Injects system prompt listing available subagents
- Includes a general-purpose subagent by default
With Nesting¶
Allow subagents to spawn their own subagents:
agent = Agent(
"openai:gpt-4.1",
capabilities=[SubAgentCapability(
subagents=[...],
max_nesting_depth=2, # Subagents can nest 2 levels deep
)],
)
YAML Agent Definition¶
# agent.yaml
model: openai:gpt-4.1
capabilities:
- SubAgentCapability:
subagents:
- name: researcher
description: Researches topics
instructions: You are a research assistant.
- name: writer
description: Writes content
instructions: You are a technical writer.
YAML/JSON loading is handled by pydantic-ai's Agent.from_file (which builds an
AgentSpec from the file). SubAgentCapability opts into this via its
get_serialization_name()
classmethod, which returns "SubAgentCapability" — the key used in the YAML
above.
Because SubAgentCapability is a third-party capability, pydantic-ai does not
register it automatically: you must declare it with custom_capability_types so
the deserializer can resolve the SubAgentCapability: block.
from pydantic_ai import Agent
from subagents_pydantic_ai import SubAgentCapability
agent = Agent.from_file(
"agent.yaml",
custom_capability_types=[SubAgentCapability],
)
Each entry under subagents: is loaded as a plain
SubAgentConfig dict.
SubAgentSpec vs Agent.from_file
SubAgentSpec is a separate,
standalone Pydantic model for when you load and parse YAML/JSON yourself
(e.g. specs = [SubAgentSpec(**s) for s in data["subagents"]], then
spec.to_config()). It is not part of the Agent.from_file path, which
deserializes the capability and its subagents dicts directly. Use
SubAgentSpec when you want validation and defaults for hand-loaded subagent
definitions.
Using the Toolset API (Alternative)¶
For lower-level control:
from pydantic_ai import Agent
from subagents_pydantic_ai import create_subagent_toolset, get_subagent_system_prompt, SubAgentConfig
configs = [
SubAgentConfig(name="researcher", description="Researches topics", instructions="..."),
]
toolset = create_subagent_toolset(subagents=configs)
agent = Agent(
"openai:gpt-4.1",
toolsets=[toolset],
system_prompt=get_subagent_system_prompt(configs),
)
Note
With SubAgentCapability, the system prompt is injected dynamically.
With the toolset API, you need to wire get_subagent_system_prompt() manually.
What Happens at Runtime¶
- User asks: "Research the benefits of async programming"
- Parent agent decides to delegate to "researcher"
- Parent calls:
task(description="...", subagent_type="researcher") - Researcher subagent executes the task
- Result is returned to parent
- Parent formats and returns final response
Next Steps¶
- Sync vs Async — Learn about execution modes
- Giving Subagents Tools — Provide capabilities to subagents
- Research Team — Build a multi-agent research pipeline