BerriAI/litellm · error · ValueError

api_base is required for PydanticAIProviderConfig

Error message

api_base is required for PydanticAIProviderConfig

What it means

PydanticAIProviderConfig.handle_non_streaming() forwards a request to a self-hosted Pydantic AI agent over HTTP and needs the agent's base URL to do so. If api_base arrives as None (it is optional in the signature), the config layer refuses to build the upstream call and raises this ValueError. In the LiteLLM A2A (agent-to-agent) routing layer, api_base comes from the deployment's litellm_params, so this almost always means the model entry for the pydantic_ai agent never configured one.

Solutions

  1. Add api_base to the deployment's litellm_params, e.g. litellm_params: {model: pydantic_ai/my-agent, api_base: http://localhost:8000}
  2. If calling programmatically, pass api_base="http://host:port" to the completion call for the pydantic_ai model
  3. Verify the param name is exactly api_base (not base_url / url) and that it sits inside litellm_params in config.yaml
  4. Confirm the Pydantic AI agent server is actually deployed at that URL and reachable from the proxy

Example fix

# before
response = litellm.completion(
    model="pydantic_ai/my-agent",
    messages=[{"role": "user", "content": "hello"}],
)

# after
response = litellm.completion(
    model="pydantic_ai/my-agent",
    messages=[{"role": "user", "content": "hello"}],
    api_base="http://localhost:8000",
)
Defensive patterns

Strategy: validation

Validate before calling

from litellm import Router

def assert_pydantic_ai_deployment_ready(deployment: dict) -> None:
    lp = deployment.get("litellm_params", {})
    if deployment["litellm_params"].get("model", "").startswith("pydantic_ai"):
        if not lp.get("api_base"):
            raise ValueError(
                f"Deployment {deployment.get('model_name')} is missing api_base"
            )

Type guard

def has_api_base(params: dict) -> bool:
    """True when params carry a usable api_base for pydantic_ai routing."""
    return isinstance(params.get("api_base"), str) and len(params["api_base"].strip()) > 0

Try / catch

try:
    result = await provider_config.handle_non_streaming(request_id, params, api_base=api_base)
except ValueError as e:
    if "api_base is required" in str(e):
        raise HTTPException(500, "Agent deployment missing api_base") from e
    raise

Prevention

When it happens

Trigger: Calling litellm.completion()/acompletion() (or the A2A proxy route) with a model whose provider is pydantic_ai while the deployment/config has no api_base in litellm_params; invoking PydanticAIProviderConfig.handle_non_streaming(request_id, params) directly without api_base; passing api_base=None explicitly.

Common situations: Adding a Pydantic AI agent to a LiteLLM proxy model_list and forgetting the api_base line; copying an OpenAI-style config (api_key only) for a pydantic_ai deployment; renaming the param to base_url or url so it is silently ignored; the agent deployment YAML indentation putting api_base outside litellm_params.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at litellm/a2a_protocol/providers/pydantic_ai_agents/config.py:29

class PydanticAIProviderConfig(BaseA2AProviderConfig):
    """
    Provider configuration for Pydantic AI agents.

    Pydantic AI agents follow A2A protocol but don't support streaming natively.
    This config provides fake streaming by converting non-streaming responses into streaming chunks.
    """

    async def handle_non_streaming(
        self,
        request_id: str,
        params: dict[str, Any],
        api_base: str | None = None,
        **kwargs: Any,
    ) -> dict[str, Any]:
        """Handle non-streaming request to Pydantic AI agent."""
        if api_base is None:
            raise ValueError("api_base is required for PydanticAIProviderConfig")
        return await PydanticAIHandler.handle_non_streaming(
            request_id=request_id,
            params=params,
            api_base=api_base,
            timeout=kwargs.get("timeout", 60.0),
            agent_extra_headers=kwargs.get("agent_extra_headers"),
        )

    async def handle_streaming(
        self,
        request_id: str,
        params: dict[str, Any],
        api_base: str | None = None,
        **kwargs,
    ) -> AsyncIterator[dict[str, Any]]:
        """Handle streaming request with fake streaming."""
        if not api_base:
            raise ValueError("api_base is required for Pydantic AI agents")

View on GitHub (pinned to 77b7c6c40c)