BerriAI/litellm · error · ValueError
api_base is required for Pydantic AI agents
Error message
api_base is required for Pydantic AI agents
What it means
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.
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
Example fix
# before
resp = await PydanticAIHandler.handle_non_streaming(
request_id=req_id, params=params, api_base=None, timeout=60.0
)
# after
resp = await PydanticAIHandler.handle_non_streaming(
request_id=req_id, params=params, api_base="http://localhost:8000", timeout=60.0
)
) Defensive patterns
Strategy: validation
Validate before calling
async def route_pydantic_ai(params: dict, request_id: str, kwargs: dict):
api_base = kwargs.get("api_base")
if api_base is None:
raise ValueError("api_base is required for Pydantic AI agents")
return await PydanticAIHandler.handle_non_streaming(
request_id=request_id, params=params, api_base=api_base
)
Try / catch
try:
resp = await PydanticAIHandler.handle_non_streaming(req_id, params, api_base)
except ValueError as e:
if "api_base is required" in str(e):
log.error("deployment config incomplete: %s", e)
raise
raise
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
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
- api_base is required for Pydantic AI agents
- api_base is required for PydanticAIProviderConfig
- api_base is required
- api_base is required
- api_base is required for A2A provider
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/0453319c83cf613b.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/a2a_protocol/providers/pydantic_ai_agents/handler.py:49
timeout: float = 60.0,
agent_extra_headers: dict[str, str] | None = None,
) -> dict[str, Any]:
"""
Handle non-streaming request to Pydantic AI agent.
Args:
request_id: A2A JSON-RPC request ID
params: A2A MessageSendParams containing the message
api_base: Base URL of the Pydantic AI agent
timeout: Request timeout in seconds
agent_extra_headers: Per-request headers (from x-a2a-{agent}-* rewrite and
admin extra_headers) to forward on the upstream HTTP call.
Returns:
A2A SendMessageResponse dict
"""
if api_base is None:
raise ValueError("api_base is required for Pydantic AI agents")
verbose_logger.info("Pydantic AI: Routing to Pydantic AI agent at %s", api_base)
# Send request directly to Pydantic AI agent
response_data: Final = await PydanticAITransformation.send_non_streaming_request(
api_base=api_base,
request_id=request_id,
params=params,
timeout=timeout,
agent_extra_headers=agent_extra_headers,
)
return response_data
@staticmethod
async def handle_streaming(
request_id: str,
params: dict[str, Any],
api_base: str | None = None,View on GitHub (pinned to 77b7c6c40c)