{"record":{"id":"0453319c83cf613b","repo":"BerriAI/litellm","slug":"api-base-is-required-for-pydantic-ai-agents-045331","errorCode":null,"errorMessage":"api_base is required for Pydantic AI agents","messagePattern":"api_base is required for Pydantic AI agents","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/a2a_protocol/providers/pydantic_ai_agents/handler.py","lineNumber":49,"sourceCode":"        timeout: float = 60.0,\n        agent_extra_headers: dict[str, str] | None = None,\n    ) -> dict[str, Any]:\n        \"\"\"\n        Handle non-streaming request to Pydantic AI agent.\n\n        Args:\n            request_id: A2A JSON-RPC request ID\n            params: A2A MessageSendParams containing the message\n            api_base: Base URL of the Pydantic AI agent\n            timeout: Request timeout in seconds\n            agent_extra_headers: Per-request headers (from x-a2a-{agent}-* rewrite and\n                admin extra_headers) to forward on the upstream HTTP call.\n\n        Returns:\n            A2A SendMessageResponse dict\n        \"\"\"\n        if api_base is None:\n            raise ValueError(\"api_base is required for Pydantic AI agents\")\n        verbose_logger.info(\"Pydantic AI: Routing to Pydantic AI agent at %s\", api_base)\n\n        # Send request directly to Pydantic AI agent\n        response_data: Final = await PydanticAITransformation.send_non_streaming_request(\n            api_base=api_base,\n            request_id=request_id,\n            params=params,\n            timeout=timeout,\n            agent_extra_headers=agent_extra_headers,\n        )\n\n        return response_data\n\n    @staticmethod\n    async def handle_streaming(\n        request_id: str,\n        params: dict[str, Any],\n        api_base: str | None = None,","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/a2a_protocol/providers/pydantic_ai_agents/handler.py#L31-L67","documentation":"PydanticAIHandler.handle_non_streaming() is the lower-level handler that sends the A2A JSON-RPC message to the Pydantic AI agent via PydanticAITransformation.send_non_streaming_request(). It hard-requires api_base because there is no default host for a self-hosted agent; None triggers this ValueError before any HTTP traffic happens. Callers normally get api_base from the model deployment's litellm_params.","triggerScenarios":"Directly calling PydanticAIHandler.handle_non_streaming(request_id, params, api_base=None); a pydantic_ai deployment in the proxy without api_base in litellm_params so the router passes None down to the handler.","commonSituations":"Writing custom A2A proxy code that constructs handler arguments manually and omitting api_base; a config.yaml typo (api-base, base_url) that leaves the real key unset; migrating a deployment between environments and dropping the agent URL.","solutions":["Configure api_base under litellm_params for the pydantic_ai model in the proxy config","When invoking the handler directly, always pass api_base=\"http://host:port\"","Log the resolved litellm_params before dispatch to confirm api_base survives config parsing","Add a startup check that every pydantic_ai deployment declares api_base"],"exampleFix":"# before\nresp = await PydanticAIHandler.handle_non_streaming(\n    request_id=req_id, params=params, api_base=None, timeout=60.0\n)\n\n# after\nresp = await PydanticAIHandler.handle_non_streaming(\n    request_id=req_id, params=params, api_base=\"http://localhost:8000\", timeout=60.0\n)\n)","handlingStrategy":"validation","validationCode":"async def route_pydantic_ai(params: dict, request_id: str, kwargs: dict):\n    api_base = kwargs.get(\"api_base\")\n    if api_base is None:\n        raise ValueError(\"api_base is required for Pydantic AI agents\")\n    return await PydanticAIHandler.handle_non_streaming(\n        request_id=request_id, params=params, api_base=api_base\n    )\n","typeGuard":null,"tryCatchPattern":"try:\n    resp = await PydanticAIHandler.handle_non_streaming(req_id, params, api_base)\nexcept ValueError as e:\n    if \"api_base is required\" in str(e):\n        log.error(\"deployment config incomplete: %s\", e)\n        raise\n    raise\n","preventionTips":["Centralize handler invocation behind one wrapper that always injects api_base from deployment metadata","Unit-test the wrapper with a None api_base to confirm the failure is caught early","Log resolved litellm_params at debug level to audit config plumbing"],"tags":["pydantic-ai","a2a","handler","api-base","configuration"],"backgroundTag":"missing-required-argument","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}