BerriAI/litellm · error · ValueError

api_base is required for A2A provider

Error message

api_base is required for A2A provider

What it means

ValueError raised by the A2A provider's get_url when api_base is None. A2A agents are addressed entirely by their base URL (JSON-RPC 2.0 at that URL; the model name does not select a host), so without api_base the request cannot be routed anywhere and fails fast.

Solutions

  1. Pass api_base explicitly: litellm.completion(model='a2a/x', api_base='http://host:9999', ...).
  2. In proxy config, add litellm_params: {model: a2a/x, api_base: http://host:9999} to the model_list entry.
  3. Check for key typos (base_url vs api_base) and that the value is not None/empty.
  4. Verify the agent is reachable at that URL and speaks A2A JSON-RPC 2.0 at the base path.

Example fix

# before
resp = litellm.completion(model="a2a/agent", messages=[{"role": "user", "content": "hi"}])
# ValueError: api_base is required for A2A provider

# after
resp = litellm.completion(
    model="a2a/agent",
    api_base="http://localhost:9999",
    messages=[{"role": "user", "content": "hi"}],
)
Defensive patterns

Strategy: validation

Validate before calling

api_base = kwargs.get("api_base") or os.getenv("A2A_API_BASE")
if not api_base:
    raise ValueError("api_base is required for A2A provider (e.g. http://localhost:9999)")
resp = litellm.completion(model="a2a/agent", api_base=api_base, messages=messages)

Type guard

def is_valid_a2a_target(api_base: object) -> bool:
    if not isinstance(api_base, str) or not api_base.strip():
        return False
    return api_base.startswith(("http://", "https://"))

Try / catch

try:
    resp = litellm.completion(model="a2a/agent", messages=messages, api_base=api_base)
except ValueError as e:
    if "api_base is required" in str(e):
        raise HTTPException(status_code=400, detail="A2A deployment is missing api_base")
    raise

Prevention

When it happens

Trigger: litellm.completion(model='a2a/my_agent', ...) with no api_base in the call, deployment, or litellm_params; api_base set under a misspelled key (base_url) or only in an unrelated env var.

Common situations: First-time A2A usage assuming a default agent registry; proxy deployments whose model_list entry for the a2a model lacks litellm_params.api_base; config migrated from another provider where the base URL key differs.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/d72dccfb8e032611. Report an issue: GitHub.

Appendix: source

Thrown at litellm/llms/a2a/chat/transformation.py:185

        Get the complete A2A agent endpoint URL.

        A2A agents use JSON-RPC 2.0 at the base URL, not specific paths.
        The method (message/send or message/stream) is specified in the
        JSON-RPC request body, not in the URL.

        Args:
            api_base: Base URL of the A2A agent (e.g., "http://0.0.0.0:9999")
            api_key: API key (not used for URL construction)
            model: Model name (not used for A2A, agent determined by api_base)
            optional_params: Optional parameters
            litellm_params: LiteLLM parameters
            stream: Whether this is a streaming request (affects JSON-RPC method)

        Returns:
            Complete URL for the A2A endpoint (base URL)
        """
        if api_base is None:
            raise ValueError("api_base is required for A2A provider")

        # A2A uses JSON-RPC 2.0 at the base URL
        # Remove trailing slash for consistency
        return api_base.rstrip("/")

    def transform_request(
        self,
        model: str,
        messages: list[AllMessageValues],
        optional_params: dict,
        litellm_params: dict,
        headers: dict,
    ) -> dict:
        """
        Transform OpenAI request to A2A JSON-RPC 2.0 format.

        Args:
            model: Model name

View on GitHub (pinned to 77b7c6c40c)