Structure of Messages Exchanged Between Agent Zero Agents: A Deep Dive into Inter-Agent Communication
Agent Zero agents communicate by sending LangChain BaseMessage objects that are converted to LiteLLM-compatible formats when delegating tasks to subordinate agents.
The open-source framework Agent Zero (agent0ai/agent-zero) implements hierarchical agent collaboration through a structured messaging protocol. When an agent delegates work to a subordinate, the system relies on LangChain message objects and LiteLLM abstraction layers to maintain conversation state. Understanding the structure of messages exchanged between Agent Zero agents is essential for debugging delegation flows and customizing agent behaviors.
The Seven-Step Message Exchange Flow
Agent Zero implements a complete request-response cycle when superior agents communicate with subordinates. The flow traverses tool invocation, history management, LLM conversion, and result propagation.
1. Tool Invocation and Subordinate Creation
The process begins when a superior agent executes the Delegation tool defined in python/tools/call_subordinate.py. At lines 29-34, the tool creates (or reuses) a subordinate Agent instance and passes a user-message (UserMessage) containing the delegation instructions.
# Inside an agent's tool registry
await self.tools["call_subordinate"].execute(
message="Summarize the following article…",
profile="researcher", # optional custom prompt profile
reset="false"
)
The tool instantiates the subordinate agent and prepares it to receive the task payload.
2. History Integration
The subordinate agent stores the incoming message using hist_add_user_message() in main/agent.py (lines 79-106). This method builds a prompt using templates like fw.user_message.md or intervention prompts, then stores the message in its History object as a new topic.
3. Monologue Execution
The subordinate executes its own message loop via Agent.monologue(). This method gathers all previously stored messages—including system prompts, user inputs, AI responses, and tool results—and prepares them for the LLM provider.
4. Message Conversion for LLM Providers
Before sending to the model, LiteLLMChatWrapper._convert_messages() (defined in models.py, lines 19-28) maps LangChain message types to LiteLLM roles. The conversion translates HumanMessage, AIMessage, SystemMessage, and ToolMessage objects into the provider-specific format with roles like user, assistant, system, and tool.
# Payload generated by _convert_messages()
msgs = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Summarize the following article…"},
# …previous AI replies, tool calls etc.
]
5. LLM Response Parsing
After the provider returns a response stream, LiteLLMChatWrapper._parse_chunk() (lines 13-27 in models.py) parses each chunk into a ChatChunk object containing response_delta and optional reasoning_delta fields.
6. History Update
The subordinate records the AI's reply using hist_add_ai_response() (lines 7-11 in main/agent.py), which stores the assistant's message in the conversation history for future context.
7. Result Propagation
Finally, the subordinate's monologue() completes and returns control to the Delegation tool. At lines 46-47 in call_subordinate.py, the tool extracts the generated text from Response.message and returns it to the superior agent, which continues its own execution loop.
Core Message Object Hierarchy
Agent Zero operates with a dual-layer message architecture that separates internal representation from LLM provider formats.
LangChain BaseMessage Objects
At the transport layer, agents exchange standard LangChain BaseMessage subclasses:
- HumanMessage – user inputs and delegation instructions
- AIMessage – generated responses and reasoning
- SystemMessage – behavioral instructions and prompts
- ToolMessage – results from tool executions
Internal Message Wrapper
The framework wraps these in a custom Message class defined in python/helpers/history.py (lines 81-88). This internal structure tracks:
ai: bool– flag indicating if message originated from the AIcontent: MessageContent– the actual text or structured contentsummary– optional condensed version for context windows- Token count metadata for usage tracking
Streaming Response Objects
During LLM interaction, partial responses are handled as ChatChunk objects—simple dictionaries containing response_delta and reasoning_delta. The ChatGenerationResult class aggregates these chunks into the final message stored in history.
Key Files and Their Roles
The message exchange protocol depends on specific components across the codebase:
python/tools/call_subordinate.py– Implements the Delegation tool that creates subordinate agents and forwards messages between hierarchy levels.main/agent.py– Contains high-level API methods includinghist_add_user_message(),hist_add_ai_response(), and themonologue()execution loop.models.py– HousesLiteLLMChatWrapperfor message conversion to provider formats and response chunk parsing.python/helpers/history.py– Defines internal data structures (Message,Topic,Bulk,History) that store conversation state and enable transcript generation.python/helpers/tool.py– BaseToolclass andResponsecontainer used by all tools including the delegation mechanism.- Prompt files (
prompts/fw.user_message.md,prompts/fw.intervention.md) – Templates that shape the user-side content of exchanged messages.
Practical Implementation Examples
Calling a Subordinate from a Running Agent
Delegate tasks programmatically using the tool registry:
await self.tools["call_subordinate"].execute(
message="Analyze the security implications of this code block",
profile="security_expert",
reset="false"
)
The tool handles subordinate lifecycle management and returns the sub-agent's output as a string.
Inspecting Subordinate Conversation History
Access the message history of a delegated agent to audit the exchange:
sub = agent.get_data(Agent.DATA_NAME_SUBORDINATE)
print(sub.history.output_text())
The History.output_text() method concatenates all Message objects into a readable transcript showing the full conversation between superior and subordinate.
Converting Messages for Custom Providers
When extending Agent Zero for new LLM backends, override the conversion logic:
# Reference implementation in models.py lines 19-28
def _convert_messages(self, messages: List[BaseMessage]) -> List[Dict]:
# Map LangChain types to provider-specific roles
return [
{"role": self._map_role(m.type), "content": m.content}
for m in messages
]
Summary
- Agent Zero agents communicate through LangChain BaseMessage objects that are internally wrapped and converted to LiteLLM formats.
- The Delegation tool in
call_subordinate.pyinitiates inter-agent communication by creating subordinate instances and passing user messages. - History management occurs through
hist_add_user_message()andhist_add_ai_response()inmain/agent.py, maintaining conversation state across the monologue loop. - Message conversion happens in
LiteLLMChatWrapper._convert_messages()(models.py), translating between LangChain types and provider-specific roles. - The Message class in
history.pyadds metadata layers for token counting and summarization on top of raw LLM messages.
Frequently Asked Questions
What message format does Agent Zero use for agent-to-agent communication?
Agent Zero uses LangChain BaseMessage objects as the canonical format, specifically HumanMessage for inputs and AIMessage for responses. These are wrapped in an internal Message class (defined in python/helpers/history.py) that adds metadata like token counts and summaries before being stored in the agent's History object.
How does Agent Zero convert messages for different LLM providers?
The LiteLLMChatWrapper class in models.py handles conversion through the _convert_messages() method (lines 19-28). It maps LangChain message types to LiteLLM-compatible dictionaries with standard roles (user, assistant, system, tool), enabling the framework to support multiple providers through a unified interface.
Where is conversation history stored in Agent Zero?
Conversation history is stored in the History object attached to each Agent instance, implemented in python/helpers/history.py. The history maintains a list of Message objects organized into topics, with methods like output_text() providing flattened transcripts. History updates occur through hist_add_user_message() and hist_add_ai_response() in main/agent.py.
How can I inspect messages exchanged between a superior and subordinate agent?
Access the subordinate agent instance via agent.get_data(Agent.DATA_NAME_SUBORDINATE) and call sub.history.output_text() to view the complete message transcript. This reveals the full structure of messages exchanged between Agent Zero agents, including system prompts, user delegations, and AI responses.
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 →