How Agent Zero Handles Task Decomposition Using a Hierarchical Structure
Agent Zero implements task decomposition by spawning lightweight subordinate agents that operate in isolated contexts and bubbling their results back up through a recursive processing chain.
The agent0ai/agent-zero framework solves complex computational problems through task decomposition using a hierarchical structure of linked agents. This architecture enables superior agents to delegate subtasks to dedicated subordinates, each running independent message loops while maintaining a bidirectional parent-child relationship. By isolating execution contexts and recursively propagating results upward, the system creates a robust tree-like execution model that scales from simple single-agent interactions to deep multi-level workflows.
Hierarchical Agent Architecture
At the core of Agent Zero's delegation system lies the Agent class defined in agent.py, which maintains hierarchical links through a free data store. According to the source code (lines 56–60 and 158–160), each agent instance tracks its position in the hierarchy using two key constants: DATA_NAME_SUPERIOR and DATA_NAME_SUBORDINATE.
# Conceptual representation based on agent.py structure
class Agent:
DATA_NAME_SUPERIOR = "superior_agent"
DATA_NAME_SUBORDINATE = "subordinate_agent"
def __init__(self, number, config, context):
self.number = number
self.config = config
self.context = context
self.data = {} # Free data store for hierarchical links
This lightweight linking mechanism allows any agent to spawn children that maintain a reference to their parent, creating a directed graph where results can flow upward while delegation flows downward.
The Delegation Tool Implementation
The actual delegation logic resides in python/tools/call_subordinate.py (lines 9–33), implemented as the execute method of the Delegation tool. When a superior agent encounters a task requiring decomposition, it invokes this tool to instantiate a fresh subordinate or reuse an existing one.
# python/tools/call_subordinate.py
async def execute(self, message="", reset="", **kwargs):
# Create a fresh subordinate if none exists or reset is requested
if (self.agent.get_data(Agent.DATA_NAME_SUBORDINATE) is None
or str(reset).lower().strip() == "true"):
config = initialize_agent()
sub = Agent(self.agent.number + 1, config, self.agent.context)
# Register the two-way link
sub.set_data(Agent.DATA_NAME_SUPERIOR, self.agent)
self.agent.set_data(Agent.DATA_NAME_SUBORDINATE, sub)
The tool registers a bidirectional relationship: the subordinate receives a reference to its superior via set_data(Agent.DATA_NAME_SUPERIOR, self.agent), while the superior stores the subordinate reference using DATA_NAME_SUBORDINATE.
Message Flow and Execution Control
Once instantiated, the subordinate receives the delegated task through its own independent message loop. The call_subordinate tool forwards the user message and awaits completion:
# python/tools/call_subordinate.py
subordinate = self.agent.get_data(Agent.DATA_NAME_SUBORDINATE)
subordinate.hist_add_user_message(UserMessage(message=message, attachments=[]))
result = await subordinate.monologue() # Subordinate runs its own loop
subordinate.history.new_topic() # Seal the subordinate's context
After the subordinate's monologue completes, the tool packages the result. For outputs exceeding length thresholds (as determined by save_tool_call_file.LEN_MIN), it attaches additional hints from the prompt system before returning the response to the superior agent.
Recursive Result Propagation
The critical mechanism enabling task decomposition using a hierarchical structure appears in agent.py (lines 85–89) within the _process_chain coroutine. This method implements the upward bubbling of results through recursive calls:
# agent.py – _process_chain implementation
response = await agent.monologue()
superior = agent.data.get(Agent.DATA_NAME_SUPERIOR, None)
if superior:
# Recursively feed the result back to the superior agent
response = await self._process_chain(superior, response, False)
When a subordinate finishes execution, its parent receives the output as a tool result. If that parent has its own superior (indicated by the presence of DATA_NAME_SUPERIOR in its data store), the result continues propagating upward until reaching the root agent—the agent with no superior. This recursion creates a seamless integration of subtask results into the broader reasoning context.
Data Access and Future Extensibility
The architecture includes placeholder functionality for hierarchical data access. In agent.py (lines 64–71), the get_data and set_data methods accept a recursive flag designed to propagate reads and writes through the entire chain:
# agent.py – data access helpers (stubbed for future recursion)
def get_data(self, key, recursive=False):
# Current implementation returns local data
# Future: if recursive and self.data.get(DATA_NAME_SUPERIOR): propagate upward
return self.data.get(key)
def set_data(self, key, value, recursive=False):
self.data[key] = value
# Future implementation may propagate to subordinates or superiors
While these recursive flags remain stubbed in the current codebase, they demonstrate the framework's design intent for deep hierarchical data propagation. All tools, prompts, and extensions operate against the same Agent API regardless of hierarchy depth, ensuring composability across levels.
Practical Usage Example
To leverage task decomposition using a hierarchical structure in your own implementation, invoke the delegation mechanism through the standard communication interface:
# Assume `agent` is the top-level Agent instance (A0)
# Request that triggers delegation to a subordinate (A1)
await agent.communicate(
UserMessage(
message="Summarize the following article and extract key take-aways.",
attachments=["https://example.com/long-article.html"]
)
)
# Internal execution flow:
# 1. A0 receives the request and determines decomposition is needed
# 2. call_subordinate creates A1, links A1 superior -> A0
# 3. A1.monologue() processes the summarization independently
# 4. Result bubbles up via _process_chain to A0
# 5. A0 incorporates the summary into its final response
This pattern ensures isolation (each sub-agent maintains independent history and state), supports parallelism (sub-agents execute in separate DeferredTask threads as defined in agent.py), and enables composability (any tool callable at any level).
Summary
Agent Zero achieves sophisticated task decomposition using a hierarchical structure through the following mechanisms:
- Bidirectional agent linking via
DATA_NAME_SUPERIORandDATA_NAME_SUBORDINATEreferences stored in eachAgentinstance's free data store. - Dynamic subordinate creation through the
call_subordinatetool inpython/tools/call_subordinate.py, which instantiates agents with incremented numbering and shared context. - Upward result propagation implemented recursively in
_process_chain(agent.pylines 85–89), allowing subtask outputs to integrate seamlessly into parent agent reasoning. - Execution isolation where each hierarchical level runs independent
monologueloops with dedicated histories, preventing cross-task contamination. - Extensible data access patterns with placeholder recursive flags in
get_data/set_datamethods preparing for future deep hierarchy data sharing.
Frequently Asked Questions
How does Agent Zero establish parent-child relationships between agents?
Agent Zero establishes hierarchical relationships through the Agent class data store using two specific keys defined in agent.py: DATA_NAME_SUPERIOR and DATA_NAME_SUBORDINATE. When a superior delegates a task, the call_subordinate tool creates a new Agent instance and immediately registers bidirectional links—the subordinate stores a reference to its parent using set_data(Agent.DATA_NAME_SUPERIOR, self.agent), while the parent stores the subordinate reference using DATA_NAME_SUBORDINATE. This two-way linkage enables both downward delegation and upward result propagation.
What happens when a subordinate agent completes its assigned task?
Upon completion, the subordinate's monologue method returns a result to the call_subordinate tool, which packages the output and returns it to the superior agent as a tool response. The superior agent's _process_chain method then receives this result (as implemented in agent.py lines 85–89). If the superior itself has a parent (indicated by the presence of DATA_NAME_SUPERIOR in its data store), the result recursively propagates upward via _process_chain until reaching the root agent, ensuring all levels of the hierarchy can incorporate subtask outputs into their reasoning.
Can subordinate agents create their own subordinates for nested decomposition?
Yes, the hierarchy supports arbitrary depth because the call_subordinate tool is available to any agent regardless of its current level. A subordinate agent can itself invoke the delegation tool, creating a new Agent instance with a number incremented from its own (e.g., agent 1 creates agent 2, which can create agent 3). Each new level establishes its own superior-subordinate links, and results bubble up through the entire chain via the recursive _process_chain calls, enabling multi-stage pipelines like "search → extract → summarize" to run across different hierarchical levels.
How does the system prevent interference between agents in the hierarchy?
Agent Zero maintains strict isolation between hierarchical levels by giving each subordinate its own independent execution context. Each agent instance manages separate history, log, and temporary state objects, ensuring that the monologue processing of one agent cannot contaminate another. Additionally, subordinates execute within their own DeferredTask threads (referencing the run_task implementation in agent.py), providing parallel execution without shared mutable state. The new_topic() call after a subordinate completes its task further seals its context before returning control upward.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →