
This blog is the third of a three part series on Agents and particularly the Agent2Agent (A2A) protocol. It will build on the two previous posts, Introduction to A2A and agent search2A and How to use MCP agents to access multiple data stores and demonstrate how A2A can enrich agent search using a “SuperAgent” and two A2A agents in front of MCP servers..
It will use the scenario from the previous blog post to show how A2A enabled agents can be used to simplify search across multiple, disparate data sources including the Bronto logging platform and how a “SuperAgent” can act autonomously to route and orchestrate requests to other agents, in a simple agentic manner.
The Scenario
The example scenario is what happens when an employee leaves a company and the IT department wants to determine that their details and access has been removed from all systems, such as the HR database and a tool such as a logging service. Traditionally, that would be done by an IT person checking each system having been notified of the employee's departure.
The use of specialized data storage systems, such as Bronto’s high-performance logging platform for searching logs, as part of an ecosystem of collaborating agents, aligns with the need for high throughput and the need to handle heterogeneous systems, as identified in a recent paper from Berkeley on agentic search.

The diagram above outlines the agents and protocols used in the demonstration. We will demonstrate:
- Using the MCP servers providing access to the Bronto REST API and the MCP server providing access to the SQLite employee database, as described in the previous blog.
- Creating A2A agents for each MCP service by extending the simple A2A agent described in the first post in the series.
- Creating a simple A2A “SuperAgent” that will access the A2A agents accessing the data stores
- The A2A “SuperAgent” answering requests about the stored user information and using A2A to call the two A2A agents to access data.
Note these examples are given for demonstration purposes only and other factors should also be considered for any other use, e.g. agent discovery could use a curated registry of agents for discovery instead of a simple well known URI as shown in these examples.
Create an A2A Bronto bronto-get-users Agent
This code is shown in Appendix 1 and it uses an MCP server to call the Bronto get_users REST API, which was described in the previous blog. The agent has two main files:
__main__.py
- This specifies the skills and extended skills that will be used in the public agent card and extended agent card (see source code in Appendix 1 for details)
- It also sets up a request_handler using the BrontoAgentExecutor() defined in agent_executor.py
- It passes the request handler and agent card information to an A2AStarletteApplication server
- Calls uvicorn.run() to run the server on the specified host and port
Agent_executor.py
This consists of:
- an __init__() call, where we Initialize the FastMCP Client (at the known URL)
- an invoke() call, where we use the FastMCP client to call a tool named "get_bronto_users" on the MCP server. In the code, we also ping the MCP server and obtain its tools for demonstration purposes.
- class BrontoAgentExecutor(AgentExecutor) which
- runs asynchronously accepting A2A messages using code for request and queue handling similar to that in the A2A samples in the official A2A samples github repository.
- calls invoke() or each A2A request, it and that calls the MCP server tool to make a call to the Bronto /users REST API and it returns the result it receives in the text part of the A2A response.
This is a simple agent implementation, for example a more complete implementation would check or summarise the message received.
Create an A2A Employee DB bronto-get-employees Agent
This agent reuses the same code as for the A2A agent above to call the MCP SQL server with the following changes:
- __main__.py
- Skills, extended skills, agent card and extended card changed to reflect this agent gets employee information from a database.
- Server updated for Host and port it listens on
- Agent_executor.py
- url changed to that for the MCP server to get_employees
- Mcp tool called updated to “get_employees”
Create an A2A “SuperAgent”
The source code for this agent is shown in Appendix 2. It acts as an A2A "SuperAgent" (Orchestrator) that routes A2A requests it receives to MCP servers based on a simple check on the query parameter it receives from an A2A client. It returns a response comprised of the response or responses it received. It consists of
__main__.py
- Skills, extended skills, agent card and extended card changed to show that this agent gets users from Bronto and employees from a database.
- Server updated for Host and port it listens on
Agent_executor.py
This gathers and checks AgentCards and routes messages accordingly.
- Holds URLs for the A2A subagents in front of the MCP servers
- SuperAgent class
- fetches the AgentCard from the .well-known/agent.json endpoint for those subagents in order to discover the agent’s capabilities and holds the cards in a registry. This is done in method discover_agents() by using a httpx client and A2ACardResolver to retrieve the AgentCard of all the agents it has a URL for.
- Provides bronto_agents() to retrieve any agent with “bronto” in its name in the AgentCard held in the registry
- uses a2a_get_text_from_response() to retrieve the text from the A2A response, as the text holds the reply from the subagent
- SuperAgentExecutor class
- Instantiates the SuperAgent class and calls discover_agents() in SuperAgent, when it is invoked
- On receiving a request from an A2A client, it decides which agent to route the request to by passing a name to call_named_agent() or to call them all using call_all_bronto_agents(), based on the query parameter it received
- call_named_agent()tries to find the name of the agent in the AgentCard registry and if it finds a matching AgentCard, it will use this AgentCard in creating an A2AClient which it will use to send an A2A message to that A2A subagent and uses a2a_get_text_from_response() to retrieve the text from the response and put that text in its own response
- call_all_bronto_agents() calls bronto_agents() to retrieve all the AgentCards with “bronto” in their name and builds and sends a combined response from all the responses it receives
This is a simple “SuperAgent” agent implementation, based on the A2A project patterns in the samples in their samples github repo. A more advanced agent could;
- Use more advanced routing to call subagents instead of the simple checks on the query parameter and the name in the AgentCard as used in this example, e.g. call an LLM to consider the full AgentCard(s) in determining whether to use an agent,
- call an LLM with a prompt and the responses it has received from the subagents and then the “SuperAgent” would take actions based on the LLM response.
Create an A2A Client
The source code for this client is shown in Appendix 3 and makes a request to the A2A “SuperAgent” to retrieve Bronto user and/or employee information. It consists of:
- a simple handler for the input argument to get the query parameter to use
- a httpx client and A2ACardResolver to retrieve the AgentCard of the “SuperAgent”
- an A2AClient is instantiated with the retrieved AgentCard
- creating an A2A message with the query passed in the text part
- sending an A2A request to the “SuperAgent” and awaiting the response
- for demo purposes, it also sends the request as a streaming message and prints the chunks returned
A2A Demonstration
Once you have the MCP servers running as described in the previous blog, you can run the A2A bronto-get-users and bronto-get-users subagents in the directories holding their source with uv run.
Similarly, you can run the “SuperAgent” in the directory holding its source with uv run .
Finally, you can run the A2A client in the directory holding its source with uv run . and a parameter of “GetEmployees” or “GetUsers” or “GetAllUserDetails” and see the “SuperAgent” send a request to the appropriate A2A subagent(s) and in turn onto the MCP Servers and then to Bronto or SQL.
In the previous blog, Claude was configured for the MCP servers and it did not require the use of A2A. The use of A2A here allows for flexibility by allowing use of a separate “SuperAgent” to discover our employee and user services and deciding whether to use them and make requests, using their agent cards.
Summary
This simple demo scenario showed that there was no need to move any data to a new database or data lake to get access to all the data in an AI agent world by using A2A and MCP. In this case the data could stay in the most suitable data storage, i.e. logs in the special purpose Bronto log platform for fast search and low cost storage and tabular HR data in a SQL database, but this data could be accessed by using agents specific to where that data was stored, with an A2A enabled “SuperAgent” orchestrating the requests to get the requested data.
This demonstrated use could be easily extended by using the “SuperAgent” to filter the data and/or aggregate the data it retrieves from its subordinate agents (such as from Bronto) and then send the filtered/aggregated data to an LLM for further analysis. This use of a “SuperAgent” would have benefits in terms of orchestrating the requests and the use of subagents, but the filtering/aggregation of data provides an opportunity to reduce the tokens used by the LLM and avoid it having to handle large volumes of data directly - the importance of managing agent costs is illustrated in this PostHog blog.
As outlined in the first blog in this series, there are a number of areas where A2A requires further development. This sample code has shown a simple case of orchestrating two agents, but as in the earlier blog Multi-Agent Orchestration would need higher level standardized support to handle complex interactions autonomously. This sample code also showed a simple use of the name in AgentCards to select an agent, but as per earlier blog, there is no agreed/shared vocabulary to define items that may be described over A2A. This could be assisted by asking LLMs to use the provided AgentCard to determine if an agent is suitable, but this would still benefit by the emergence of a shared vocabulary. Challenges also remain in establishing trust between agents, security (beyond authentication), scalability and enterprise readiness.
A2A has, however, standardized agent communication and the samples here have shown it makes it simple to build interoperable agents. Whether A2A will be widely adopted and become the enabler for a rich ecosystem of collaborating AI agents or whether the ecosystem will be custom point solutions using MCP servers remains to be seen…but Bronto’s high performance logging platform will be part of this ecosystem, using the Bronto remote MCP server and/or A2A.
Code Samples for A2A Clients
Note: All code samples here are for demonstration purposes only as the code is not written for efficiency or with comprehensive error handling. For example, the code manipulating requests and responses could be improved using pydantic, but that is not shown here to keep the code similar to what is used in the official A2A Samples github repo.
Appendix 1- A2A Client Code to access Bronto /users API
__main__.py
agent_executor.py
Appendix 2 - “SuperAgent” Code
__main__.py
agent_executor.py




