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 a Task tool it can use to delegate work to them.

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
)

Sub-agents do not inherit MCP servers from the coordinator. Provide mcp_servers on AgentDefinition explicitly if a sub-agent needs them.


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, context: SubagentHookContext) -> None:
print(f"Sub-agent starting: {hook_input['child_name']}")

async def on_subagent_stop(hook_input: dict, context: 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
)