Skip to content

Provider-specific Responses capability filtering for gateways without custom tools / hosted web_search #5002

Closed

Description

@1395490241lhj-code

Client or integration

Codex CLI and Codex App

Provider or upstream service

Agent.Space

OpenCodex version

2.58.0

Endpoint or capability

OpenAI Responses API at https://api.agent.space/v1/responses, specifically Responses custom tools and hosted web_search.

Current behaviour

Agent.Space works for plain Responses requests and standard function tools, but rejects Responses custom tools and hosted web_search with HTTP 400 unsupported_request.

When the provider is routed through OpenCodex, Codex advertises/forwards those capabilities even for a simple text-only prompt. As a result, a request such as Reply exactly with OK fails before the model can answer.

Direct provider tests:

  • Plain Responses request -> HTTP 200
  • Standard function tool -> HTTP 200
  • custom tool such as apply_patch -> HTTP 400 unsupported_request
  • hosted web_search -> HTTP 400 unsupported_request

Setting supportsResponsesCustomTools: false fixes the custom-tool mismatch, but the request still fails because hosted web_search is also sent.

Temporarily running Codex with web_search="disabled" succeeds.

Expected behaviour

OpenCodex should allow provider-specific Responses capability filtering so a routed provider only receives capabilities it supports.

For this provider, standard Responses and function tools should continue to work while unsupported native custom tools and hosted web-search declarations are omitted or downgraded. This should not require disabling web search globally for unrelated providers that support it.

Minimal redacted request or reproduction

# 1. Normal routed Codex request fails:
codex exec \
  --skip-git-repo-check \
  -m agent-space/gpt-5.6-luna \
  "Reply exactly with OK"

# 2. Direct Agent.Space Responses request with a standard function tool succeeds:
curl -sS -w '\nHTTP %{http_code}\n' \
  https://api.agent.space/v1/responses \
  -H "Authorization: Bearer <redacted>" \
  -H "Content-Type: application/json" \
  -d '{
    "model":"gpt-5.6-luna",
    "input":"Reply exactly with OK.",
    "tools":[{
      "type":"function",
      "name":"noop",
      "description":"Do nothing",
      "parameters":{
        "type":"object",
        "properties":{},
        "additionalProperties":false
      }
    }]
  }'
# => HTTP 200

# 3. Direct custom tool request is rejected:
curl -sS -w '\nHTTP %{http_code}\n' \
  https://api.agent.space/v1/responses \
  -H "Authorization: Bearer <redacted>" \
  -H "Content-Type: application/json" \
  -d '{
    "model":"gpt-5.6-luna",
    "input":"Reply exactly with OK.",
    "tools":[{
      "type":"custom",
      "name":"apply_patch",
      "description":"Apply a patch",
      "format":{"type":"text"}
    }]
  }'
# => HTTP 400

# 4. Direct hosted web_search request is rejected:
curl -sS -w '\nHTTP %{http_code}\n' \
  https://api.agent.space/v1/responses \
  -H "Authorization: Bearer <redacted>" \
  -H "Content-Type: application/json" \
  -d '{
    "model":"gpt-5.6-luna",
    "input":"Reply exactly with OK.",
    "tools":[{"type":"web_search"}]
  }'
# => HTTP 400

# 5. Disabling hosted web search for this Codex invocation succeeds:
codex -c 'web_search="disabled"' exec \
  --skip-git-repo-check \
  -m agent-space/gpt-5.6-luna \
  "Reply exactly with OK"
# => OK

Actual response or error

ERROR: {
  "error": {
    "message": "The request uses an invalid or unsupported capability.",
    "type": "invalid_request_error",
    "param": null,
    "code": "unsupported_request"
  }
}

OpenCodex request history also records the routed request as provider: agent-space, model: gpt-5.6-luna, status 400, with the same upstream error.

Upstream documentation

https://agent.space/developer-api

Agent.Space documents an OpenAI-compatible Responses API and Codex integration, but the tested endpoint currently does not accept native Responses custom tools or hosted web_search for this model.

Suggested mapping or implementation notes

A provider-level capability setting would avoid hard-coded destination rules. For example:

{
  "providers": {
    "agent-space": {
      "adapter": "openai-responses",
      "supportsResponsesCustomTools": false,
      "unsupportedHostedTools": [
        "web_search",
        "web_search_preview"
      ]
    }
  }
}

Then the existing hosted-tool filtering path could consult provider configuration.

As a local workaround, I added a provider-specific rule in src/responses/hosted-tool-policy.ts:

{
  match: (_model, baseUrl) =>
    baseUrl?.replace(/\/+$/, "") === "https://api.agent.space/v1",
  tools: new Set(["web_search", "web_search_preview"]),
},

Together with supportsResponsesCustomTools: false, the same Codex CLI request succeeds and Codex App also works with the routed model.

Additional context and attachments

Environment:

  • macOS
  • Codex CLI 0.153.4
  • OpenCodex 2.58.0
  • Adapter: openai-responses
  • Tested model: gpt-5.6-luna

The issue is broader than Agent.Space: any OpenAI-compatible Responses gateway with a narrower capability set can hit the same mismatch if unsupported capabilities are advertised/forwarded unconditionally.

Checks

  • I searched existing provider and compatibility issues.
  • The request and response were redacted.
  • The expected behaviour is based on an upstream specification or a concrete client requirement.

Activity

  1. added
    providerProvider adapters, OpenAI-compat presets, upstream API quirks
    on Sep 18, 2026
  2. github-actions commented on Sep 18, 2026

    @github-actions
    Contributor

    Issue reopened

    The report now contains the information required by the automated check. Thanks for updating it.

  3. lidge-jun commented on Sep 18, 2026

    @lidge-jun
    Owner

    Fixed on dev by #5021, squashed as 48a23dd9a00e947ce0e714ea46f74e1ea05d56a2.

    The answer is config-declarative rather than a per-vendor rule, and that was forced by your case: the only existing mechanism was a table of (model, baseUrl) predicates in src/responses/hosted-tool-policy.ts, so a narrower gateway needed a proxy release naming its endpoint. Agent.Space is not in this repository at all — it is a user-defined provider — so a built-in entry could never have covered it.

    Providers can now declare unsupportedHostedTools, and stripUnsupportedHostedTools consults that alongside the built-in table across tools, additional_tools and tool_choice. The configuration you suggested in the report works verbatim. The declaration is additive, so it can only deny more and can never re-enable a pairing already known to be broken.

    Two design calls worth knowing about. web_search and web_search_preview are aliased, because the rest of the proxy already folds that pair into one tool — honouring only the spelling an operator happened to write would have reproduced your 400 while the config claimed otherwise. And the value is validated against a closed vocabulary rather than accepted freeform, because the provider schema is .passthrough() and #2106 is the recorded lesson about a typo in a config key silently doing nothing.

    The custom-tool half needed no code: supportsResponsesCustomTools already existed and you confirmed it works.

    No registry entry sets the new field, so nothing ships dead and no existing provider changes behaviour. Shipping in the next release off dev.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    providerProvider adapters, OpenAI-compat presets, upstream API quirksprovider-compatibilityProvider compatibility reportstoolstool_calls, MCP, web-search / sidecar tools

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions