Understanding the Agent Communication Protocol (ACP): A Comprehensive Guide

The Agent Communication Protocol (ACP) is a standardized, framework-agnostic protocol that enables seamless communication and collaboration among software agents, regardless of the underlying framework used to create them, such as CrewAI, LangChain, LangGraph, or others. By leveraging RESTful architecture, ACP facilitates dynamic, interoperable, and scalable agent interactions, drawing inspiration from HTTP, which transformed web connectivity in 1988. This blog provides a detailed exploration of ACP’s mechanics, features, and applications, emphasizing automatic agent selection in chaining workflows and clarifying the distinction between ACP and the Multi-Agent Communication Protocol (MCP).

What is ACP?

ACP is a protocol designed to enable software agents — specialized software entities that perform specific tasks — to discover, communicate, and collaborate efficiently. Its framework-agnostic nature means agents built with diverse tools like CrewAI, LangChain, LangGraph, or custom frameworks can interoperate seamlessly, as long as they adhere to ACP’s standardized communication model. This flexibility makes ACP a powerful tool for building modular, scalable systems that integrate across organizational boundaries.

Key Features of ACP

ACP offers several capabilities that enhance agent-based systems:

  1. Dynamic Updating: Agents can be swapped or updated without disrupting the system, ensuring adaptability.
  2. Team-Based Collaboration: Specialized agents can work together, eliminating the need for monolithic multi-agent architectures.
  3. Cross-Company Workflows: Agents representing different departments within a company can coordinate tasks like data analysis or inventory management.
  4. Inter-Organizational Collaboration: Agents from different organizations can collaborate, for example, on production schedules or logistics optimization.
  5. REST-Based Communication: ACP uses REST for lightweight, standardized client-server interactions.
  6. Framework Agnosticism: ACP’s design allows it to connect agents built with any framework, such as CrewAI, LangChain, or LangGraph, fostering interoperability across diverse ecosystems.

How ACP Works

ACP wraps agents in a server that handles requests and responses via REST, ensuring compatibility with web technologies. Below, I’ll detail the core components and processes.

Wrapping Agents in an ACP Server

To make an agent ACP-compliant, developers use the @server.agent() decorator in Python, which defines the agent’s identity and functionality. The agent’s name is derived from the function name, and its purpose is described in a docstring. Here’s an example of an ACP-compliant agent for policy-related queries:

from acp_sdk.server import Server
from acp_sdk.models import Message, MessagePart
from collections.abc import AsyncGenerator

server = Server()

@server.agent()
async def policy_agent(input: list[Message]) -> AsyncGenerator[RunYield, RunYieldResume]:
"This agent answers policy coverage questions using a Retrieval-Augmented Generation (RAG) pattern, ideal for queries on coverage and waiting periods."
task_output = ... # Logic to process input and retrieve answers
yield Message(parts=[MessagePart(content=str(task_output))])

Client-Server Interaction

An ACP client discovers available servers and sends requests. The server processes the request and returns a response via REST. For example, a client can query a policy agent:

from acp_sdk.client import Client
import asyncio
from colorama import Fore

async def example() -> None:
async with Client(base_url="http://localhost:8001") as client:
run = await client.run_sync(
agent="policy_agent", input="What is the waiting period for rehabilitation?"
)
print(Fore.YELLOW + run.output[0].parts[0].content + Fore.RESET)

asyncio.run(example())

Running an ACP Server

To activate an agent, the server must run. Below is an example using the Smolagents framework, compatible with tools like CrewAI or LangChain, to create a health-focused agent:

from collections.abc import AsyncGenerator
from acp_sdk.models import Message, MessagePart
from acp_sdk.server import Context, RunYield, RunYieldResume, Server
from smolagents import CodeAgent, DuckDuckGoSearchTool, LiteLLMModel, VisitWebpageTool
from dotenv import load_dotenv

load_dotenv()

server = Server()

model = LiteLLMModel(model_id="openai/gpt-4", max_tokens=2048)

@server.agent()
async def health_agent(input: list[Message], context: Context) -> AsyncGenerator[RunYield, RunYieldResume]:
"This agent answers health-related questions for hospital patients, using search and webpage tools."
agent = CodeAgent(tools=[DuckDuckGoSearchTool(), VisitWebpageTool()], model=model)
prompt = input[0].parts[0].content
response = agent.run(prompt)
yield Message(parts=[MessagePart(content=str(response))])

if __name__ == "__main__":
server.run(port=8000)

Chaining Agent Calls with Automatic Agent Selection

ACP excels at coordinating multiple agents through chaining, with a particular emphasis on hierarchical chaining using a router agent for automatic agent selection based on requirements. This approach is prioritized over sequential chaining due to its ability to dynamically assign tasks to the most suitable agents.

Hierarchical Chaining with Automatic Agent Selection

Hierarchical chaining involves a router agent that analyzes a complex query, breaks it into smaller tasks, and automatically selects the appropriate specialized agents based on their capabilities. For example, a query like “Do I need rehabilitation after shoulder surgery, and what’s the insurance waiting period?” requires both medical and policy expertise. The router agent identifies these needs and delegates tasks accordingly.

Here’s how it works:

  1. Agent Discovery: The router discovers available agents (e.g., health and policy agents) by querying their servers and converting them into tools.
  2. Task Delegation: The router breaks down the query and assigns tasks to specialized agents via their clients.

Here’s an example of a router agent orchestrating a workflow:

from acp_sdk.client import Client
import asyncio
from smolagents import CodeAgent, DuckDuckGoSearchTool, LiteLLMModel

async def run_hospital_workflow() -> None:
async with Client(base_url="http://localhost:8001") as insurer, Client(base_url="http://localhost:8000") as hospital:
# Router agent logic (simplified)
router = CodeAgent(tools=[DuckDuckGoSearchTool()], model=LiteLLMModel(model_id="openai/gpt-4"))
query = "Do I need rehabilitation after shoulder surgery, and what's the waiting period?"
tasks = router.analyze(query) # Hypothetical task breakdown
# Task 1: Health-related query
if "rehabilitation need" in tasks:
run1 = await hospital.run_sync(
agent="health_agent", input="Do I need rehabilitation after shoulder reconstruction?"
)
health_response = run1.output[0].parts[0].content
# Task 2: Policy-related query
if "waiting period" in tasks:
run2 = await insurer.run_sync(
agent="policy_agent", input=f"Context: {health_response} What is the waiting period for rehabilitation?"
)
policy_response = run2.output[0].parts[0].content
print(f"Health: {health_response}nPolicy: {policy_response}")

asyncio.run(run_hospital_workflow())

This example shows how the router agent dynamically selects the health agent and policy agent based on the query’s requirements, leveraging ACP’s framework-agnostic nature to integrate agents built with different tools.

Sequential Chaining (Secondary Approach)

Sequential chaining, while effective, is less dynamic as it follows a predefined order. For example, a hospital agent’s output is passed to an insurer agent:

import nest_asyncio
nest_asyncio.apply()
from acp_sdk.client import Client
import asyncio
from colorama import Fore

async def run_hospital_workflow() -> None:
async with Client(base_url="http://localhost:8001") as insurer, Client(base_url="http://localhost:8000") as hospital:
run1 = await hospital.run_sync(
agent="health_agent", input="Do I need rehabilitation after a shoulder reconstruction?"
)
content = run1.output[0].parts[0].content
print(Fore.LIGHTMAGENTA_EX + content + Fore.RESET)

run2 = await insurer.run_sync(
agent="policy_agent", input=f"Context: {content} What is the waiting period for rehabilitation?"
)
print(Fore.YELLOW + run2.output[0].parts[0].content + Fore.RESET)

asyncio.run(run_hospital_workflow())

While sequential chaining is straightforward, it lacks the flexibility of automatic agent selection, which makes hierarchical chaining more powerful for complex workflows.

Comparing ACP to MCP and A2A

While ACP focuses on standardized client-server communication, MCP extends this to multi-agent coordination, and A2A likely refers to direct agent-to-agent interactions. MCP builds on ACP’s foundation, enabling more complex workflows, as seen in hierarchical chaining. More details can be found in the image attached below.

Where ACP Fits in the Tech Stack

ACP is a middleware layer, bridging agents with clients and other systems. Its REST-based design ensures compatibility with existing web technologies, and its framework-agnostic nature allows integration with diverse agent frameworks. As shown in the above image, the ACP fits seamlessly into the tech stack, enabling efficient communication with minimal overhead.

Real-World Applications

ACP’s versatility and framework agnosticism make it applicable across industries:

  1. Healthcare: A health agent, built with LangChain or CrewAI, can answer patient queries using search tools.
  2. Insurance: A policy agent, possibly using LangGraph, can retrieve coverage details via RAG.
  3. Manufacturing and Logistics: Agents from different organizations, regardless of their framework, can collaborate on production schedules or route optimization.
  4. Multi-Agent Systems: ACP supports modular workflows, reducing the complexity of large-scale systems.

Conclusion

The Agent Communication Protocol (ACP) is a transformative, framework-agnostic protocol that enables seamless agent communication and collaboration. Its support for dynamic updates, team-based workflows, and automatic agent selection through hierarchical chaining makes it ideal for complex, scalable systems. By integrating with MCP, ACP extends its capabilities to orchestrate multi-agent workflows across organizations. Whether in healthcare, insurance, or logistics, ACP’s flexibility and standardization, combined with its compatibility with frameworks like CrewAI, LangChain, and LangGraph, position it as a cornerstone for the future of agent-driven automation.

For developers, the provided code examples demonstrate how to wrap agents, run servers, and implement hierarchical chaining with automatic agent selection. As agent-based technologies evolve, ACP’s role as a unifying protocol will drive innovation across industries.

Resources

  1. https://www.deeplearning.ai/short-courses/acp-agent-communication-protocol/


Understanding the Agent Communication Protocol (ACP): A Comprehensive Guide was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

Liked Liked