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 AI
  • content: MessageContent – the actual text or structured content
  • summary – 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 including hist_add_user_message(), hist_add_ai_response(), and the monologue() execution loop.
  • models.py – Houses LiteLLMChatWrapper for 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 – Base Tool class and Response container 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.py initiates inter-agent communication by creating subordinate instances and passing user messages.
  • History management occurs through hist_add_user_message() and hist_add_ai_response() in main/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.py adds 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →