Multi-agent communication is the core functionality of any multi-agent system. Unlike all other frameworks, Agency Swarm not only allows you to define communication flows in any way you want (uniform communication flows), but also to configure the underlying logic for this feature. This means that you can create entirely new types of communication or adjust it to your own needs. Below you will find a guide on how to do all this, along with some common examples.

Pre-Made SendMessage Classes

Agency Swarm contains multiple commonly requested classes for communication flows. Currently, the following classes are available:
Class NameDescriptionWhen to UseCode Link
SendMessage (default)This is the default class for sending messages to other agents. It uses synchronous communication with basic COT (Chain of Thought) prompting and allows agents to relay files and modify system instructions for each other.Suitable for most use cases. Balances speed and functionality.link
SendMessageHandoffEnables unidirectional delegation of tasks or entire interaction flows to specialized agents. When a handoff occurs, the receiving agent takes over the interaction.Use for routing queries to specialized agents or sequential workflows where control should transfer completely.link
There are 3 main ways to define custom custom send message tools:

Agency-level

from agency_swarm import Agent
from agency_swarm.tools import SendMessageHandoff

agent = Agent(
    name="MyAgent",
    instructions="You are a helpful assistant.",
)

agency = Agency(agent, send_message_tool_class=SendMessageHandoff)
That sets a default send message tool for all agents that do not have it explicitly defined.

Agent-level

from agency_swarm import Agent
from agency_swarm.tools import SendMessageHandoff

agent = Agent(
    name="MyAgent",
    instructions="You are a helpful assistant.",
    send_message_tool_class=SendMessageHandoff
)

agency = Agency(agent)
In this example, agent will be using a custom send message for every interaction with other agents. This setting will override custom agency send message tool, if present.

Communication-level

from agency_swarm import Agent
from agency_swarm.tools import SendMessageHandoff

ceo = Agent(
    name="CeoAgent",
    instructions="You are a helpful assistant.",
)

worker = Agent(
    name="WorkerAgent",
    instructions="You are a helpful assistant.",
)

agency = Agency(ceo, communication_flows=[(ceo > worker, SendMessageHandoff)])
Here, the SendMessageHandoff tool will be used specifically for ceo -> worker communication and nowhere else. If there were other agents in the agency connected to ceo, they would be using regular SendMessage for agent-to-agent conversations. This setting overrides both agency and agent-level custom send message tools within this particular thread.

Choosing the Right Communication Method: SendMessage vs. handoffs

Agency Swarm supports two primary paradigms for inter-agent communication: direct messaging using SendMessage tool variants (native to Agency Swarm) and handoffs via the SendMessageHandoff tool class.

Direct Messaging (SendMessage tools)

  • Purpose: Use Agency Swarm’s SendMessage tools (e.g., SendMessage) when one agent needs to request information or a discrete action from another, expecting a response to continue its own work. Unlike in handoffs, control returns to the calling agent, making this suitable for true collaboration and agent orchestration.
  • Data Exchange: Primarily string-based messages, with support for file attachments.
  • Analogy: An orchestrator agent assigning a sub-task to a worker agent and awaiting the result to proceed.
  • When to use:
    • Implementing orchestrator-worker pattern.
    • Collaborative tasks requiring back-and-forth dialogue (evaluator-optimizer pattern) or result aggregation by a calling agent.
    • When an agent needs to retain control of the overall workflow while delegating specific parts.

Handoffs (via SendMessageHandoff)

  • Purpose: The SendMessageHandoff tool class enables an agent to unidirectionally delegate a task or an entire interaction flow to another specialized agent. When a handoff occurs, the receiving agent takes over that specific interaction; control does not automatically return to the initiating agent for that particular interaction thread.
  • How it Works: From the perspective of the underlying language model, a handoff is treated like a special tool (e.g., transfer_to_BillingAgent). To enable handoffs, you configure an agent with the send_message_tool_class=SendMessageHandoff parameter. The agent’s description will be used as the handoff tool instructions.
  • Configuration: Set send_message_tool_class=SendMessageHandoff when creating the agent. The framework will automatically detect this and configure handoffs using the OpenAI SDK internally.
  • Analogy: Transferring a customer in a call center to a specialized department (e.g., Billing). The Billing specialist handles the customer’s request from that point forward for that specific issue.
  • When to use (handoffs):
    • Routing Use Cases: Such as an initial customer support agent routing a query to a specialized support agent (e.g., for billing, technical issues). A new, focused interaction begins with the specialist.
    • Sequential interaction flows: Where a task must pass through a series of different specialists, and each specialist completes their part and passes it on, without the original agent resuming that specific flow.
  • Further Details: For comprehensive information on configuring and utilizing handoffs, consult the Hybrid Patterns Documentation.

Creating Your Own Unique Communication Flows

To create your own communication flow, you will first need to extend the FunctionTool class from the agents SDK. In v1.x, the SendMessage class is built on top of FunctionTool, providing a flexible foundation for creating custom communication patterns tailored to your specific needs.

Custom SendMessage Class

To customize SendMessage parameters, extend the SendMessage class and declare additional fields using a Pydantic model:
from pydantic import BaseModel, Field
from agency_swarm.tools.send_message import SendMessage

class CustomSendMessage(SendMessage):
    """
    Use this tool to facilitate direct, synchronous communication between specialized agents within your agency.
    """
    
    class ExtraParams(BaseModel):
        key_moments: str = Field(description="Critical context and decision points relevant to the task")
        decisions: str = Field(description="Specific decisions that guide tool choice and approach")

    def __init__(self, sender_agent, recipients=None):
        super().__init__(sender_agent, recipients)
        self.name = "send_message_custom"  # Optional: custom name for this tool

Key Components

In general, all SendMessage tools in v1.x have the following components:
  1. FunctionTool Base: Extends the FunctionTool class from the agents SDK, providing async execution and standardized tool interfaces.
  2. Dynamic Initialization: Tools are created dynamically for specific sender->recipient pairs with custom parameter schemas.
  3. JSON Schema: Parameters are defined using JSON schema for validation and type safety.
  4. Async Communication: Uses async/await for non-blocking communication between agents.
When creating your own SendMessage tools, extend FunctionTool and implement the on_invoke_tool method with your custom communication logic.
If you are planning to create an agent that has access to multiple SendMessage tools (using communication flow pattern), each tool must have a unique name, which must start with send_message. For example, name="send_message_formatted" or name="send_message_custom" and so on.

Common Use Cases

For detailed Common Use Cases, please refer to the Common Use Cases subpage.

Conclusion

Agency Swarm has been designed to give you, the developer, full control over your systems. It is the only framework that does not hard-code any prompts, parameters, or even worse, agents for you. With this new feature, the last part of the system that you couldn’t fully customize to your own needs is now gone! So, we want to encourage you to keep experimenting and designing your own unique communication flows. While the examples above should serve as a good starting point, they do not even merely scratch the surface of what’s possible here! We are looking forward to seeing what you will create. Please share it in our Discord server so we can all learn from each other.