2025, Sep 28 19:00
Fix python-a2a A2A client ErrorContent: get function_response by using the correct base URL and endpoint
Learn why a python-a2a client receives ErrorContent instead of function_response, and how to fix it using the correct base URL, endpoint, and port 5001.
When integrating a lightweight function-calling agent with python-a2a, a common stumbling block looks like a perfectly valid request that returns an error envelope instead of a function_response. The console prints are explicit: the client attempted to reach the agent, tried multiple endpoint variations, and still reported an error response type.
Unexpected response type from A2A agent: error. Full response content: ErrorContent(message='Failed to communicate with agent ... Tried multiple endpoint variations.')
Code example that surfaces the symptom
The following minimal agent and client illustrate the setup. The behavior here performs basic arithmetic and returns results via function_response. The logic below mirrors a working pattern.
import math
from python_a2a import (
    A2AServer, Message, TextContent, FunctionCallContent,
    FunctionResponseContent, FunctionParameter, MessageRole, run_server,
    Task
)
class MathOpsNode(A2AServer):
    def handle_message(self, msg):
        if msg.content.type == "text":
            return Message(
                content=TextContent(
                    text="I'm a [Python A2A](python-a2a.html) calculator agent. You can call my functions:\n"
                         "- calculate: Basic arithmetic (operation, a, b)\n"
                         "- sqrt: Square root (value)"
                ),
                role=MessageRole.AGENT,
                parent_message_id=msg.message_id,
                conversation_id=msg.conversation_id
            )
        elif msg.content.type == "function_call":
            fname = msg.content.name
            args_map = {p.name: p.value for p in msg.content.parameters}
            try:
                if fname == "calculate":
                    op = args_map.get("operation", "add")
                    x = float(args_map.get("a", 0))
                    y = float(args_map.get("b", 0))
                    if op == "add":
                        out_val = x + y
                    elif op == "subtract":
                        out_val = x - y
                    elif op == "multiply":
                        out_val = x * y
                    elif op == "divide":
                        if y == 0:
                            raise ValueError("Cannot divide by zero")
                        out_val = x / y
                    else:
                        raise ValueError(f"Unknown operation: {op}")
                    return Message(
                        content=FunctionResponseContent(
                            name="calculate",
                            response={"result": out_val}
                        ),
                        role=MessageRole.AGENT,
                        parent_message_id=msg.message_id,
                        conversation_id=msg.conversation_id
                    )
                elif fname == "sqrt":
                    val = float(args_map.get("value", 0))
                    if val < 0:
                        raise ValueError("Cannot calculate square root of negative number")
                    out_val = math.sqrt(val)
                    return Message(
                        content=FunctionResponseContent(
                            name="sqrt",
                            response={"result": out_val}
                        ),
                        role=MessageRole.AGENT,
                        parent_message_id=msg.message_id,
                        conversation_id=msg.conversation_id
                    )
            except Exception as err:
                return Message(
                    content=FunctionResponseContent(
                        name=fname,
                        response={"error": str(err)}
                    ),
                    role=MessageRole.AGENT,
                    parent_message_id=msg.message_id,
                    conversation_id=msg.conversation_id
                )
if __name__ == "__main__":
    svc = MathOpsNode()
    run_server(svc, host="0.0.0.0", port=5001)
import python_a2a
from python_a2a import (
    A2AClient, Message, FunctionCallContent,
    FunctionParameter, MessageRole
)
class CalcA2AInvoker:
    """
    Encapsulates interaction with a Python A2A agent.
    """
    def __init__(self, base_url: str):
        """
        Args:
            base_url: The A2A agent base URL (e.g., "http://127.0.0.1:5001").
        """
        self.conn = A2AClient(base_url)
        print(f"CalcA2AInvoker initialized for URL: {base_url}")
    def request_compute(self, operation: str, a: int, b: int) -> int | None:
        print(f"Sending calculation request: {operation}(a={a}, b={b})")
        call_payload = FunctionCallContent(
            name="calculate",
            parameters=[
                FunctionParameter(name="operation", value=operation),
                FunctionParameter(name="a", value=a),
                FunctionParameter(name="b", value=b)
            ]
        )
        outbound_msg = Message(
            content=call_payload,
            role=MessageRole.USER
        )
        try:
            reply = self.conn.send_message(outbound_msg)
            if reply.content.type == "function_response":
                result = reply.content.response.get("result")
                if result is not None:
                    print(f"Received result from A2A agent: {result}")
                    return result
                else:
                    print("Function response received, but 'result' key is missing.")
                    return None
            else:
                print(f"Unexpected response type from A2A agent: {reply.content.type}")
                print(f"Full response content: {reply.content}")
                return None
        except Exception as ex:
            print(f"An error occurred while communicating with the A2A agent: {ex}")
            return None
if __name__ == "__main__":
    endpoint = "http://127.0.0.1:5001"
    client = CalcA2AInvoker(endpoint)
    res = client.request_compute(operation="add", a=5, b=3)
    if res is not None:
        print(f"Addition Result: {res}")
    print("-" * 30)
What’s actually going wrong
The client prints that it sent a calculate request and then reports an error response type. The error payload explicitly says it failed to communicate with the agent and shows concrete paths like /tasks/send or an appended /a2a/a2a. The package attempts multiple endpoint variations behind the scenes; if none succeed, it returns ErrorContent with type error.
Locally, running the agent and client as above produces a valid function_response with the expected numeric result. This indicates the code itself is sound. The failure mode aligns with a connectivity problem to the base URL and port combination or using a mismatched base URL that doesn’t resolve to the running agent process.
There are environment data points that support this. One setup ran the same pattern successfully on Linux Mint with Python 3.13 and python-a2a 0.5.9. Another setup tried on Ubuntu with the firewall disabled and still saw failure, which reinforces that the issue is not inherent to the example logic and may hinge on reachability and the effective target address.
Resolution
Use the agent base URL directly and avoid appending extra path segments. The agent is started on port 5001 in the example, and a working run used http://127.0.0.1:5001 as the client’s base URL. If you point to a different host or a non-local address, confirm the address is correct and reachable, and that traffic on port 5001 is allowed in both directions. It also helps to verify in a browser that the agent is running at the intended address. If you are operating across machines, ensure the destination is the one actually running the agent service and that your routing sends traffic there.
The code below is the same calling pattern shown earlier, with the base URL set to the agent’s listening address.
if __name__ == "__main__":
    endpoint = "http://127.0.0.1:5001"  # use the base URL without extra path
    client = CalcA2AInvoker(endpoint)
    res = client.request_compute(operation="add", a=5, b=3)
    if res is not None:
        print(f"Addition Result: {res}")
    print("-" * 30)
Why this matters
When a client returns ErrorContent that says “Failed to communicate with agent … Tried multiple endpoint variations,” it’s easy to suspect a package or version issue. In reality, confirming the base URL, the exact address in use, and port reachability typically saves time. It prevents a detour into dependency debugging when the transport path is the true bottleneck.
Takeaways
Start with the simplest path: run both pieces locally with http://127.0.0.1:5001 and confirm you receive function_response. If you must use a non-local address, validate that the agent is actually up at that address, that the base URL matches how the agent is exposed, and that port 5001 is permitted. There is at least one known-good combination—Linux Mint, Python 3.13, python-a2a 0.5.9—where the example runs as expected, which underscores the importance of verifying connectivity before changing code. If disabling a firewall doesn’t help in your environment, return to the URL and routing checks; the error output already hints that the client cannot complete a request to the intended endpoint.