{"record":{"id":"d72dccfb8e032611","repo":"BerriAI/litellm","slug":"api-base-is-required-for-a2a-provider","errorCode":null,"errorMessage":"api_base is required for A2A provider","messagePattern":"api_base is required for A2A provider","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/a2a/chat/transformation.py","lineNumber":185,"sourceCode":"        Get the complete A2A agent endpoint URL.\n\n        A2A agents use JSON-RPC 2.0 at the base URL, not specific paths.\n        The method (message/send or message/stream) is specified in the\n        JSON-RPC request body, not in the URL.\n\n        Args:\n            api_base: Base URL of the A2A agent (e.g., \"http://0.0.0.0:9999\")\n            api_key: API key (not used for URL construction)\n            model: Model name (not used for A2A, agent determined by api_base)\n            optional_params: Optional parameters\n            litellm_params: LiteLLM parameters\n            stream: Whether this is a streaming request (affects JSON-RPC method)\n\n        Returns:\n            Complete URL for the A2A endpoint (base URL)\n        \"\"\"\n        if api_base is None:\n            raise ValueError(\"api_base is required for A2A provider\")\n\n        # A2A uses JSON-RPC 2.0 at the base URL\n        # Remove trailing slash for consistency\n        return api_base.rstrip(\"/\")\n\n    def transform_request(\n        self,\n        model: str,\n        messages: list[AllMessageValues],\n        optional_params: dict,\n        litellm_params: dict,\n        headers: dict,\n    ) -> dict:\n        \"\"\"\n        Transform OpenAI request to A2A JSON-RPC 2.0 format.\n\n        Args:\n            model: Model name","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/a2a/chat/transformation.py#L167-L203","documentation":"Raised by the A2A provider's URL builder in litellm when transforming a completion request: A2A agents are addressed purely by their api_base (JSON-RPC 2.0 at the base URL), so no api_base means no endpoint to call, and the transformation layer refuses with ValueError instead of constructing a broken URL. The trailing slash is stripped for consistency; model/api_key are not used for URL construction.","triggerScenarios":"Calling litellm.completion(..., model='a2a/your-agent') (or a custom A2A deployment) without api_base — e.g. router/model_list entry for an A2A model missing the api_base field, or passing api_base=None explicitly.","commonSituations":"Configuring litellm Router/proxy with an a2a/ model but forgetting 'api_base' in the model_list entry; environment variable for A2A agent URL not set (litellm_params templating yields None); copy-pasting a config from an OpenAI-style model where api_base was optional; version changes that made api_base required for A2A.","solutions":["Set api_base to the A2A agent's URL (e.g. 'http://localhost:9999') in the litellm_params of your model config / completion call.","If using environment templates (api_base: os.environ/A2A_BASE_URL), verify the variable is set in the proxy's environment.","For the proxy, add the field to config.yaml: model_list: - model_name: my-agent, litellm_params: { model: a2a/my-agent, api_base: http://host:9999 }."],"exampleFix":"# before\nresponse = litellm.completion(\n    model=\"a2a/my-agent\",\n    messages=[{\"role\": \"user\", \"content\": \"hi\"}],\n)  # ValueError: api_base is required for A2A provider\n\n# after\nresponse = litellm.completion(\n    model=\"a2a/my-agent\",\n    api_base=\"http://127.0.0.1:9999\",\n    messages=[{\"role\": \"user\", \"content\": \"hi\"}],\n)","handlingStrategy":"validation","validationCode":"if model.startswith(\"a2a/\") and not api_base:\n    raise ValueError(\"api_base is required for A2A models\")\n\nresponse = litellm.completion(model=model, api_base=api_base, messages=messages)","typeGuard":"def is_a2a_ready(model: str, api_base) -> bool:\n    return not model.startswith(\"a2a/\") or isinstance(api_base, str) and api_base.strip() != \"\"","tryCatchPattern":"try:\n    response = litellm.completion(model=\"a2a/agent\", api_base=api_base, messages=messages)\nexcept ValueError as e:\n    if \"api_base is required\" in str(e):\n        raise HTTPException(400, \"A2A model is missing api_base configuration\")\n    raise","preventionTips":["Always set api_base (agent URL) in litellm_params for every a2a/ model_list entry.","Validate required env vars for api_base at proxy startup, not per-request.","Include an A2A config smoke test (one completion call) in deployment checks."],"tags":["a2a","config","api-base","provider","valueerror"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}