BerriAI/litellm · error · ValueError

'wxo_agent_id' is required in litellm_params for WXO agents

Error message

'wxo_agent_id' is required in litellm_params for WXO agents

What it means

Watsonx Orchestrate exposes each deployed agent under its own agent id, used in the /v1/agents/{wxo_agent_id}/runs endpoint. _extract_litellm_params() treats wxo_agent_id as mandatory and raises this ValueError when it is absent or empty, before any request is built. Without it LiteLLM cannot address any specific agent.

Solutions

  1. Copy the agent id from Watsonx Orchestrate (the identifier in the agent's API details) into wxo_agent_id
  2. Confirm it is the agent id, not the agent name or skill name
  3. Ensure the key is spelled wxo_agent_id and lives inside litellm_params
  4. Restart the proxy after updating config.yaml

Example fix

# before
litellm_params:
  model: watsonx_orchestrate/my-agent
  cp4d_host: https://cp4d.example.com
  instance_id: 6c9b...
  api_key: os.environ/WXO_API_KEY

# after
litellm_params:
  model: watsonx_orchestrate/my-agent
  cp4d_host: https://cp4d.example.com
  instance_id: 6c9b...
  wxo_agent_id: my-agent-id    # technical id from WXO, not display name
  api_key: os.environ/WXO_API_KEY
Defensive patterns

Strategy: validation

Validate before calling

def validate_wxo_agent(litellm_params: dict) -> None:
    if not litellm_params.get("wxo_agent_id"):
        raise ValueError("watsonx_orchestrate deployment requires the technical wxo_agent_id")

Try / catch

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

Prevention

When it happens

Trigger: A watsonx_orchestrate deployment missing wxo_agent_id; passing the agent display name instead of the agent id; env-var-backed value unset; empty string after templating.

Common situations: Grabbing the human-readable agent name from the WXO console instead of the technical agent id; config generated from IaC where the agent id field is optional; re-creating an agent in WXO gets a new id while the proxy config keeps the old (that yields 404-style run errors, but a deleted/blank field yields this one).

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/ffa05487d8506415. Report an issue: GitHub.

Appendix: source

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

                continue
            chunk_text = WatsonxOrchestrateTransformation.extract_text_from_wxo_result(event)
            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],

View on GitHub (pinned to 77b7c6c40c)