BerriAI/litellm · error · ValueError

'api_key' is required in litellm_params for WXO agents

Error message

'api_key' is required in litellm_params for WXO agents

What it means

Every Watsonx Orchestrate call authenticates with an api_key (exchanged for a CP4D or IAM token), so _extract_litellm_params() requires a non-empty api_key in litellm_params. Missing or blank values raise this ValueError up front, before the token exchange. This is the credentials check for the WXO provider.

Solutions

  1. Add api_key (the CP4D/IAM service apikey) to the deployment's litellm_params
  2. If referencing os.environ/WXO_API_KEY, export it in the environment where the proxy actually runs and restart
  3. Verify the other required WXO keys are present in the same block
  4. Never inline real keys in committed config — use env var indirection

Example fix

# before
litellm_params:
  model: watsonx_orchestrate/my-agent
  cp4d_host: https://cp4d.example.com
  instance_id: 6c9b...
  wxo_agent_id: my-agent-id

# after
litellm_params:
  model: watsonx_orchestrate/my-agent
  cp4d_host: https://cp4d.example.com
  instance_id: 6c9b...
  wxo_agent_id: my-agent-id
  api_key: os.environ/WXO_API_KEY   # ensure WXO_API_KEY is exported
Defensive patterns

Strategy: validation

Validate before calling

import os

def validate_wxo_credentials() -> None:
    if not os.environ.get("WXO_API_KEY"):
        raise RuntimeError("WXO_API_KEY not set; WXO agents cannot authenticate")

Try / catch

try:
    result = await WatsonxOrchestrateHandler.handle_request(params)
except ValueError as e:
    if "'api_key' is required" in str(e):
        raise HTTPException(500, "WXO deployment missing api_key") from e
    raise

Prevention

When it happens

Trigger: A watsonx_orchestrate deployment without api_key in litellm_params; api_key: os.environ/WXO_API_KEY where the env var is not set in the proxy's environment; an empty string leaking through from a secrets template.

Common situations: Env var present locally but missing in the container/service running LiteLLM; secret managers failing to render the key in one environment; service-level API keys rotated and the old one deleted without updating the proxy.

Related errors


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

Appendix: source

Thrown at litellm/a2a_protocol/providers/watsonx_orchestrate/handler.py:203

            if chunk_text:
                accumulated_text += chunk_text
        return accumulated_text

    @staticmethod
    def _extract_litellm_params(litellm_params: dict[str, Any]) -> WXORequestParams:
        cp4d_host: Final = litellm_params.get("cp4d_host") or ""
        instance_id: Final = litellm_params.get("instance_id") or ""
        wxo_agent_id: Final = litellm_params.get("wxo_agent_id") or ""
        api_key: Final = litellm_params.get("api_key") or ""

        if not cp4d_host:
            raise ValueError("'cp4d_host' is required in litellm_params for WXO agents")
        if not instance_id:
            raise ValueError("'instance_id' is required in litellm_params for WXO agents")
        if not wxo_agent_id:
            raise ValueError("'wxo_agent_id' is required in litellm_params for WXO agents")
        if not api_key:
            raise ValueError("'api_key' is required in litellm_params for WXO agents")

        return WXORequestParams(
            cp4d_host=cp4d_host,
            instance_id=instance_id,
            wxo_agent_id=wxo_agent_id,
            api_key=api_key,
            username=litellm_params.get("username") or None,
            auth_mode=litellm_params.get("auth_mode") or "cp4d",
            thread_id=litellm_params.get("thread_id") or None,
        )

    @staticmethod
    async def handle_non_streaming(
        request_id: str,
        params: dict[str, Any],
        litellm_params: dict[str, Any],
    ) -> dict[str, Any]:
        wxo: Final = WatsonxOrchestrateHandler._extract_litellm_params(litellm_params)

View on GitHub (pinned to 77b7c6c40c)