Skip to main content

Multi-Agent Orchestration

Agentix supports coordinator / sub-agent patterns. Define sub-agents on the coordinator's options; the coordinator automatically receives an Agent tool it can use to delegate work to them.

How it works

The coordinator receives an Agent tool automatically when agents are configured. It delegates tasks to sub-agents by calling that tool; each sub-agent runs its own independent agent loop and returns a result. Sub-agents are isolated — they do not inherit the coordinator's MCP servers or skills.

Multi-Agent Orchestration diagram

Basic setup

from agentix import AgentixAgentOptions, AgentixClient, AgentDefinition, ResultMessage

options = AgentixAgentOptions(
name="coordinator",
provider="anthropic",
model="claude-sonnet-4-20250514",
system_prompt="You are a coordinator. Delegate research to the researcher and writing to the writer.",
agents={
"researcher": AgentDefinition(
name="researcher",
description="Searches the web and gathers information on a topic.",
tools=["WebSearch", "WebFetch"],
),
"writer": AgentDefinition(
name="writer",
description="Takes research notes and produces polished written content.",
tools=["Read", "Write"],
),
}
)

async def main():
async with AgentixClient(options) as client:
async for msg in client.query("Write a short article about Python asyncio."):
if isinstance(msg, ResultMessage):
print(msg.result)

AgentDefinition fields

from agentix import AgentDefinition

AgentDefinition(
name="my-sub-agent", # required — must match the dict key in agents={}
description="What it does.", # required — shown to the coordinator when delegating
prompt="", # additional system prompt injected for this sub-agent
tools=["Read", "Glob"], # allow-list of tools; empty = inherit coordinator's config
provider="openai", # optional — override LLM provider
model="gpt-4o", # optional — override model
memory="none", # "none" | "user" | "project" | "local" — persistent memory scope
skills=None, # None = default discovery; explicit list to restrict
mcp_servers={}, # sub-agent-specific MCP configs (not inherited from coordinator)
disallow_system_skills=[], # exclude specific built-in skills; "all" disables all
agent_type=None, # optional label for hook differentiation
)

::: warning Sub-agent isolation Sub-agents do not inherit MCP servers or user/project skills from the coordinator. If a sub-agent needs MCP tools, declare them explicitly in AgentDefinition.mcp_servers. If it needs skills, set skills explicitly — None triggers default discovery only for general-purpose agents. :::


Sub-agent memory scoping

The memory field controls where a sub-agent stores persistent memories across runs:

ValueStorage locationUse when
"none"Sub-agent is stateless (default)
"project".agentix/ (relative to cwd)Sub-agent builds per-project knowledge
"user"~/.agentix/Sub-agent learns user preferences across projects
"local".agentix-local/Machine-local facts; not committed to source control
AgentDefinition(
name="researcher",
description="Gathers and retains domain knowledge.",
tools=["WebSearch", "WebFetch"],
memory="project", # researcher accumulates knowledge in .agentix/
)

See Memory for the full guide on agent and sub-agent memory.


Hooks for sub-agent events

from agentix import HookMatcher, SubagentHookContext

async def on_subagent_start(hook_input: dict, tool_use_id: str | None, ctx: SubagentHookContext) -> None:
print(f"Sub-agent starting: {hook_input['child_name']}")

async def on_subagent_stop(hook_input: dict, tool_use_id: str | None, ctx: SubagentHookContext) -> None:
print(f"Sub-agent finished: {hook_input['child_name']}")

options = AgentixAgentOptions(
hooks={
"SubagentStart": [HookMatcher(matcher=None, hooks=[on_subagent_start])],
"SubagentStop": [HookMatcher(matcher=None, hooks=[on_subagent_stop])],
}
)

File-based sub-agent definitions

Sub-agents can also be defined as Markdown files under .agentix/agents/. The coordinator discovers them automatically when cwd is set.

---
name: researcher
description: Searches the web and summarises findings.
tools:
- WebSearch
- WebFetch
memory: project
---

You are a research specialist. Always cite your sources.

Programmatic definitions in AgentixAgentOptions.agents take precedence over file-based ones with the same name.


Built-in fallback agent

When no registered sub-agent matches a delegation request, Agentix falls back to the built-in agentix_general_agent — a capable general-purpose agent that inherits the coordinator's provider and model. It is always registered and requires no configuration.


Strict agent validation

Enable strict_agent_validation to catch configuration errors at startup — recommended for CI:

options = AgentixAgentOptions(
strict_agent_validation=True, # raises ConfigurationError on invalid sub-agent definitions
agents={
"writer": AgentDefinition(
name="writer",
description="", # ← empty description raises ConfigurationError
)
}
)

Provider and model override

Sub-agents inherit the coordinator's provider and model by default. Override per sub-agent:

AgentDefinition(
name="cheap-summariser",
description="Summarises long documents quickly.",
tools=["Read"],
provider="openai",
model="gpt-4o-mini", # cheaper model for simple summarisation
)