# Client

The A2A client allows you to connect to remote A2A agent servers and interact with them as if they were local agents. This guide covers everything you need to know about using A2A clients.

Warning

`A2aRemoteAgent` supports only asynchronous methods - this is the limitation of the A2A client we use.

## Basic Client Setup

Generally, you can use `A2aRemoteAgent` like any other `ConversableAgent`. In the example below, we specify a remote agent and start a chat between a local agent and that remote agent, asking them to generate code.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>``` | ```<br>from autogen.a2a import A2aRemoteAgent<br># Connect to a remote agent<br>remote_agent = A2aRemoteAgent(<br>    url="http://localhost:8000",<br>    name="python_coder"<br>)<br># Use it like any other agent<br>await local_agent.a_initiate_chat(<br>    recipient=remote_agent,<br>    message={<br>        "role": "user",<br>        "content": "Create a calculator function",<br>    }<br>)<br>``` |

Here's another example of a `A2aRemoteAgent` client agent working with a local agent, with the conversation printed out afterwards.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>18<br>19<br>20<br>21<br>22<br>23<br>24<br>25<br>26<br>27<br>28<br>29<br>30<br>31<br>32<br>33<br>``` | ```<br>import asyncio<br>from autogen import ConversableAgent, LLMConfig<br>from autogen.a2a import A2aRemoteAgent<br># Configure local agent<br>llm_config = LLMConfig({ "model": "gpt-4o-mini" })<br>reviewer = ConversableAgent(<br>    name="code_reviewer",<br>    system_message="You are a code reviewer...",<br>    llm_config=llm_config,<br>)<br># Connect to remote agent<br>coder = A2aRemoteAgent(<br>    url="http://localhost:8000",<br>    name="python_coder"<br>)<br># Start conversation<br>async def review_code():<br>    await reviewer.a_initiate_chat(<br>        recipient=coder,<br>        message={"role": "user", "content": "Create a Python calculator"}<br>    )<br>    # Process the response<br>    messages = reviewer.chat_messages[coder.name]<br>    for message in messages:<br>        print(f"{message['name']}: {message['content']}")<br># Run the conversation<br>asyncio.run(review_code())<br>``` |

### Creating from AgentCard

If you already have an `AgentCard` (e.g., fetched from a discovery service or another source), you can create an `A2aRemoteAgent` instance directly from it using the `from_card` classmethod. This avoids redundant fetching of the agent card and allows you to use pre-validated card information.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>``` | ```<br>from a2a.compat.v0_3.types import AgentCard, AgentCapabilities<br># Create or fetch an AgentCard<br>card = AgentCard(<br>    name="python_coder",<br>    url="http://localhost:8000",<br>    description="A Python coding assistant",<br>    version="0.1.0",<br>    default_input_modes=["text"],<br>    default_output_modes=["text"],<br>    capabilities=AgentCapabilities(streaming=True),<br>    skills=[],<br>    supports_authenticated_extended_card=False,<br>)<br># Create the remote agent from the card<br>remote_agent = A2aRemoteAgent.from_card(card)<br>``` |

## Human in the Loop (HITL) Support

`A2aRemoteAgent` automatically handles Human in the Loop interactions when the remote agent requests human input. This happens transparently - you don't need to write any special code to handle HITL requests. The client will loop until the agent completes its task or the conversation terminates.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>``` | ```<br>from autogen.a2a import A2aRemoteAgent<br># Connect to a remote agent that may request human input<br>remote_agent = A2aRemoteAgent(<br>    url="http://localhost:8000",<br>    name="approval_agent"<br>)<br># The client will automatically handle any human input requests<br>await local_agent.a_initiate_chat(<br>    recipient=remote_agent,<br>    message={<br>        "role": "user",<br>        "content": "Should I approve this budget proposal?",<br>    }<br>)<br># If the remote agent requests input, the user will be prompted automatically<br>``` |

The input prompt from the remote agent will be displayed to the user, and their response will be sent back to continue the conversation seamlessly.

## Advanced Usage

### Custom HTTP Client

Commonly, you will need to set some custom options on the remote agent's HTTP client, such as headers, timeout, etc. To do this, pass your own `HttpxClientFactory` instance to the `A2aRemoteAgent` constructor.

|     |     |
| --- | --- |
| ```<br> 1<br> 2<br> 3<br> 4<br> 5<br> 6<br> 7<br> 8<br> 9<br>10<br>11<br>12<br>13<br>14<br>15<br>16<br>17<br>``` | ```<br>import httpx<br>from autogen.a2a import A2aRemoteAgent, HttpxClientFactory<br># Create custom HTTP client factory<br>http_client = HttpxClientFactory(<br>    timeout=30.0,<br>    headers={<br>        "User-Agent": "MyApp/1.0",<br>        "Authorization": f"Bearer {your_token}"<br>    }<br>)<br>remote_agent = A2aRemoteAgent(<br>    url="http://localhost:8000",<br>    name="python_coder",<br>    client=http_client<br>)<br>``` |

### Client Configuration

The A2A client has a few configuration options that you can pass to the `A2aRemoteAgent` constructor, use the `client_config` parameter and a `ClientConfig` to do that.

|     |     |
| --- | --- |
| ```<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>``` | ```<br>from a2a.client import ClientConfig<br>from autogen.a2a import A2aRemoteAgent<br>remote_agent = A2aRemoteAgent(<br>    url="http://localhost:8000",<br>    name="python_coder",<br>    client_config=ClientConfig(streaming=True),<br>)<br>``` |

### A2aRemoteAgent testing

To help with testing remote clients, you can mock remote agent replies by passing a `MockClient` instance to the `A2aRemoteAgent` constructor.

|     |     |
| --- | --- |
| ```<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>``` | ```<br>from autogen.a2a import A2aRemoteAgent, MockClient<br>remote_agent = A2aRemoteAgent(<br>    url="http://localhost:8000",<br>    name="python_coder",<br>    client=MockClient(response_message="Hello, user!"),<br>)<br>``` |

## Interoperability with other frameworks

A2A is also supported [by other frameworks](https://a2a-protocol.org/latest/community/#a2a-integrations), so you can use `A2aRemoteAgent` with them, too.

As an example, you can connect your AG2 agents with [Pydantic AI](https://ai.pydantic.dev/a2a/) agents. Here we create a Pydantic AI agent:

| server.py |
| --- |
| ```<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>``` | ```<br>from pydantic_ai import Agent<br>agent = Agent(<br>    "openai:gpt-4.1",<br>    instructions="You are an expert Python developer...",<br>)<br>app = agent.to_a2a()<br>``` |

And now, without any changes, your `A2aRemoteAgent` clients can interact with them:

| client.py |
| --- |
| ```<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>``` | ```<br>from autogen.a2a import A2aRemoteAgent<br># works correctly with other frameworks A2A servers<br>remote_agent = A2aRemoteAgent(<br>    url="http://localhost:8000",<br>    name="python_coder",<br>)<br>``` |

Back to top
