BerriAI/litellm · error · ValueError

Either a2a_client or api_base is required for standard A2A f

Error message

Either a2a_client or api_base is required for standard A2A flow

What it means

Raised by asend_message in the standard A2A flow when neither an `a2a_client` nor an `api_base` was supplied. The function must either reuse an existing A2A client or build one from a base URL; with neither, there is no way to reach the agent.

Source

Thrown at litellm/a2a_protocol/main.py:464

    if custom_llm_provider:
        if request is None:
            raise ValueError("request is required for completion bridge")
        return await _send_message_via_completion_bridge(
            request=request,
            custom_llm_provider=custom_llm_provider,
            api_base=api_base,
            litellm_params=litellm_params,
            agent_extra_headers=agent_extra_headers,
        )

    # Standard A2A client flow
    if request is None:
        raise ValueError("request is required")

    # Create A2A client if not provided but api_base is available
    if a2a_client is None:
        if api_base is None:
            raise ValueError("Either a2a_client or api_base is required for standard A2A flow")
        trace_id = trace_id or str(uuid.uuid4())
        extra_headers: Final[dict[str, str]] = {"X-LiteLLM-Trace-Id": trace_id}
        if agent_id:
            extra_headers["X-LiteLLM-Agent-Id"] = agent_id
        # Overlay agent-level headers (agent headers take precedence over LiteLLM internal ones)
        if agent_extra_headers:
            extra_headers.update(agent_extra_headers)
        a2a_client = await create_a2a_client(base_url=api_base, extra_headers=extra_headers)

    # Type assertion: a2a_client is guaranteed to be non-None here
    assert a2a_client is not None

    agent_name: Final = _get_a2a_model_info(a2a_client, kwargs)

    verbose_logger.info("A2A send_message request_id=%s, agent=%s", request.id, agent_name)

    # Get agent card URL for localhost retry logic
    agent_card: Final = _get_a2a_client_agent_card(a2a_client)

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Pass `api_base` (e.g. "http://localhost:10001") so a client is auto-created
  2. Or create a client once with `create_a2a_client(base_url=...)` and pass it as `a2a_client` for connection reuse

Example fix

# before
resp = await asend_message(request=req)
# after
resp = await asend_message(request=req, api_base="http://localhost:10001")
Defensive patterns

Strategy: validation

Validate before calling

if a2a_client is None and not api_base:
    raise ValueError("configure api_base or pass a2a_client")
resp = await asend_message(request=request, a2a_client=a2a_client, api_base=api_base)

Prevention

When it happens

Trigger: `await asend_message(request=req)` with both a2a_client=None and api_base=None (no custom_llm_provider routing).

Common situations: Missing `api_base` in the model config when calling through LiteLLM proxy/gateway; refactoring code that previously created the client inline and dropping the base URL.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/849f8bea093d77ef. Report an issue: GitHub.