{"record":{"id":"0f3541fe766c0b4f","repo":"VectifyAI/PageIndex","slug":"responses-cannot-drive-model-name-provider","errorCode":null,"errorMessage":"responses() cannot drive '{model_name}': provider-prefixed models route through LiteLLM, which speaks chat.completions, not the Responses API. Use chat_completions() (or messages() for Anthropic models), or point OPENAI_BASE_URL at a Responses-capable backend and use a bare or 'openai/'-prefixed model name.","messagePattern":"responses\\(\\) cannot drive '(.+?)': provider-prefixed models route through LiteLLM, which speaks chat\\.completions, not the Responses API\\. Use chat_completions\\(\\) \\(or messages\\(\\) for Anthropic models\\), or point OPENAI_BASE_URL at a Responses-capable backend and use a bare or 'openai/'-prefixed model name\\.","errorType":"exception","errorClass":"PageIndexAPIError","httpStatus":null,"severity":"error","filePath":"pageindex/local_chat.py","lineNumber":192,"sourceCode":"            \"Agents SDK — \"\n            \"pip install openai-agents. \"\n            \"messages() runs on the anthropic extra instead.\"\n        ) from exc\n\n\ndef _sdk_backend(backend) -> dict:\n    \"\"\"chat_backend for an SDK constructor: LiteLLM takes either endpoint\n    spelling, the openai and anthropic SDKs only ``base_url``.\"\"\"\n    return {(\"base_url\" if key == \"api_base\" else key): value\n            for key, value in (backend or {}).items()}\n\n\ndef _openai_model(protocol: str, model_name: str, backend=None):\n    \"\"\"The backend protocol driver — the seam tests replace with a fake.\"\"\"\n    if protocol == \"responses\":\n        model_name = model_name.removeprefix(\"litellm/\")\n        if \"/\" in model_name and not model_name.startswith(\"openai/\"):\n            raise PageIndexAPIError(\n                f\"responses() cannot drive '{model_name}': provider-prefixed \"\n                \"models route through LiteLLM, which speaks chat.completions, \"\n                \"not the Responses API. Use chat_completions() (or messages() \"\n                \"for Anthropic models), or point OPENAI_BASE_URL at a \"\n                \"Responses-capable backend and use a bare or \"\n                \"'openai/'-prefixed model name.\"\n            )\n        import openai\n        model_name = model_name.removeprefix(\"openai/\")\n        try:\n            sdk_client = openai.AsyncOpenAI(**_sdk_backend(backend))\n        except (openai.OpenAIError, TypeError) as exc:\n            raise PageIndexAPIError(\n                f\"The OpenAI backend is not configured: {exc}\") from exc\n        # A caller-owned transport must survive the per-call close.\n        sdk_client._pageindex_caller_http = \"http_client\" in (backend or {})\n        from agents.models.openai_responses import OpenAIResponsesModel\n        return OpenAIResponsesModel(model_name, openai_client=sdk_client)","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/VectifyAI/PageIndex/blob/afb5e119766630af6014b04fe8b53357527bc05e/pageindex/local_chat.py#L174-L210","documentation":"responses() speaks the OpenAI Responses API, but provider-prefixed model names (e.g. 'anthropic/claude-...', 'groq/...') route through LiteLLM, which only implements chat.completions. The library refuses the combination rather than failing opaquely at request time. 'openai/'-prefixed and bare names are allowed.","triggerScenarios":"client.responses(model=\"anthropic/claude-sonnet-4\", ...) or model=\"groq/llama-3\" with responses().","commonSituations":"Copy-pasting LiteLLM-style model strings from docs, switching a working chat_completions call to responses() without changing the model name, using a gateway that expects provider prefixes.","solutions":["Use chat_completions() for provider-prefixed models","For Anthropic models, use messages()","Or drop the prefix / use 'openai/...' and point OPENAI_BASE_URL at a Responses-capable backend"],"exampleFix":"# before\nclient.responses(model=\"anthropic/claude-sonnet-4\", input=q)\n\n# after\nclient.chat_completions(model=\"anthropic/claude-sonnet-4\", messages=[{\"role\":\"user\",\"content\":q}])","handlingStrategy":"validation","validationCode":"def engine_for(model: str) -> str:\n    m = model.removeprefix('litellm/')\n    return 'responses' if ('/' not in m or m.startswith('openai/')) else 'chat_completions'","typeGuard":"def responses_compatible(model: str) -> bool:\n    m = model.removeprefix('litellm/')\n    return '/' not in m or m.startswith('openai/')","tryCatchPattern":"null","preventionTips":["Keep a per-provider engine mapping in config","Don't reuse LiteLLM model strings across surfaces","Use bare names + OPENAI_BASE_URL for Responses-capable gateways"],"tags":["pageindex","responses-api","litellm","model-name","routing"],"backgroundTag":"model-provider-routing-mismatch","analyzedSha":"afb5e119766630af6014b04fe8b53357527bc05e","analyzedAt":"2026-08-27T11:20:48.519Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}