To complete the picture, in this blog post we are going to build a hello world ACP application. As with the A2A demonstration, we will also create a simple server and client application to demonstrate the basic programming model with ACP. ACP does a good job in their getting quickstart guide: https://github.com/i-am-bee/acp
Server
server = Server()
@server.agent()
async def say_hi(
input: list[Message], context: Context
) -> AsyncGenerator[RunYield, RunYieldResume]:
"""Say hi"""
for message in input:
yield "Hi there!"
server.run()
- The say_hi function is essential here, it will be invoked by the framework when a respective request is processed
- The example just yields a hard coded string, the say_hi function would be the wrapper around your agent, here you could invoke your CrewAI agent, for example
This is the output we see, when we run the server:

Client
async def hello() -> None:
async with Client(base_url="http://localhost:8000") as client:
run = await client.run_sync(
agent="say_hi",
input=[
Message(
parts=[MessagePart(content="Hello ACP!", content_type="text/plain")]
)
],
)
print(run.output)
if __name__ == "__main__":
asyncio.run(hello())
- First we create a new client, connecting our client to the ACP server
- Then the say_hi agent is invoked
- The result is printed
And this is what we would see in the output of the client python program:

Conclusion
If you read the blog post on A2A, you will identify a lot of parallels. ACP is basically a wrapper around your agent, written in any framework of your choice. To get started, ACP requires less code – thanks to the decorators. The two blog posts on A2A and ACP are not meant to provide any advice, but I hope the looking at the actual code helps to demystify some of the buzz words.