Deferred; no hosted-search execution fix landed
The four-track delivery did not implement a raw Responses passthrough search/continuation bridge. Search-result insertion, mixed-tool continuity and replay semantics remain outstanding. This issue stays open.
Verified against dev 5759d9ea2f1e7281cdc01eb9628f2e0a123fb59c. Original report by @foo1maker. The attribution record was added in #3811.
Client or integration
Codex App
Provider or upstream service
Ollama Cloud (https://ollama.com/v1, key-auth openai-responses passthrough)
OpenCodex version
2.43.0 (@bitkyc08/opencodex)
Endpoint or capability
/v1/responses + hosted {type:"web_search"} / webSearchSidecar
Current behaviour
Codex App always speaks Responses to OpenCodex (POST /v1/responses) and advertises the hosted tool {type:"web_search"}.
For a key-auth provider with adapter: "openai-responses" (Ollama Cloud GLM / DeepSeek, etc.) OpenCodex takes the passthrough branch in src/server/responses/core.ts and returns before runWithWebSearch. planWebSearch / shouldResolveOpenAiWebSearchSidecar also fail closed on isPassthrough:
// src/web-search/index.ts
if (!parsed._webSearch || isPassthrough) return undefined;
The comment assumes passthrough means ChatGPT, which already executes hosted search server-side.
Ollama Cloud does not execute OpenAI hosted {type:"web_search"} on /v1/responses. The model instead emits a client function_call named web_search. Two failures follow:
-
Stock responses-undeclared-tool-guard treats that echo as an undeclared client tool and aborts the SSE stream:
routed provider emitted undeclared client tool "web_search"; only request-declared tools may be called
Codex App then reconnects 5/5 and the worker/turn dies (last_agent_message: null).
-
If the guard is relaxed, Codex App still does not execute a function named web_search (it expects the provider to run hosted search). The next hop is unsupported call: web_search. The model can continue without live results. Dashboard webSearchSidecar (e.g. gpt-5.6-luna) stays idle.
Ollama does have a working search API, but it is a separate client-executed REST endpoint, not ChatGPT hosted search:
Official OpenCodex backends (openai / anthropic / xai / gemini / exa) never call it. The sidecar loop that would intercept a synthetic web_search function tool never runs on this passthrough path.
Switching the provider to openai-chat would enter the sidecar loop, but Codex App cannot be switched off Responses, and translating GLM/DeepSeek off /v1/responses drops reasoning summaries and the native tool surface that this client requires.
Expected behaviour
On key-auth Responses passthrough to a gateway that does not execute OpenAI hosted web_search:
- Do not abort the stream for a
function_call named web_search when the request catalog already declared hosted {type:"web_search"} (same catalog entry, different wire shape).
- Intercept that call in the proxy (do not relay it to Codex as an unsupported client tool).
- Execute search and inject results as
function_call_output (and/or a hosted web_search_call item Codex understands).
- Prefer Ollama's own
POST /api/web_search when the route is Ollama Cloud (same credential, no ChatGPT sidecar spend). Luna/Exa remain valid fallbacks for translated routes, which is the current sidecar design.
Passthrough should keep meaning “preserve the Responses wire”, not “the upstream is ChatGPT and already searched”.
Minimal redacted request or reproduction
{
"defaultProvider": "ollama-relay",
"webSearchSidecar": { "enabled": true },
"providers": {
"ollama-relay": {
"adapter": "openai-responses",
"baseUrl": "https://ollama.com/v1",
"authMode": "key",
"selectedModels": ["glm-5.3-flash"]
},
"openai": {
"adapter": "openai-responses",
"baseUrl": "https://chatgpt.com/backend-api/codex",
"authMode": "forward"
}
}
}
# Codex App
model = "glm-5.3-flash"
openai_base_url = "http://127.0.0.1:10100/v1"
ocx start (2.43.0 stock).
- In Codex App, ask a routed GLM/DeepSeek turn for current web facts (pricing, docs, anything that triggers search).
- Observe either the undeclared-tool abort or
unsupported call: web_search with no sidecar / no POST https://ollama.com/api/web_search.
Actual response or error
stream disconnected before completion: routed provider emitted undeclared client tool "web_search"; only request-declared tools may be called
If that guard is bypassed, the Codex client hop is:
unsupported call: web_search
Upstream GLM item shape (redacted):
{
"type": "function_call",
"name": "web_search",
"arguments": "{\"query\":\"site:example.com current pricing\"}"
}
OpenCodex logs show no [web-search] sidecar enter on these turns. Ollama /api/web_search is not requested.
Upstream documentation
Suggested mapping or implementation notes
Stock code already has the intercept loop for translated adapters (runWithWebSearch + buildWebSearchTool). The gap is that adapter.passthrough both:
- skips that loop (
planWebSearch(..., isPassthrough) / early return in core.ts), and
- forwards hosted
{type:"web_search"} unchanged, which Ollama echoes as a named function_call.
A minimal passthrough-aware path:
- In
addNamelessClientCallTypes, treat hosted web_search / web_search_preview as authorizing a client function_call named web_search (same catalog, echo shape). This at least stops Mode 2 / App workers from 5/5-dying.
- On non-forward (
authMode: "key") passthrough SSE, intercept function_call name === "web_search", run an executor, hide the synthetic call from Codex, inject the tool result into the next upstream hop.
- Add an
ollama web-search backend that POSTs https://ollama.com/api/web_search with the existing provider key. Keep luna for openai-chat / Anthropic routes.
Do not require operators to change Codex App to Chat Completions. The App wire is Responses; Ollama Cloud also speaks /v1/responses. The missing piece is executing search for that pair.
Additional context
Searched existing issues. Closest prior art is passthrough tool-surface gaps (e.g. #1950 tool_search rewrite on Responses passthrough) and web-search sidecar bugs on translated openai-chat routes (#265, #1001). I did not find an open issue for Ollama Cloud hosted-web_search echo vs /api/web_search.
Related but separate: Ollama /v1/responses also lacks previous_response_id store (documented). statelessResponses addresses replay; it does not execute search.
Checks
Deferred; no hosted-search execution fix landed
The four-track delivery did not implement a raw Responses passthrough search/continuation bridge. Search-result insertion, mixed-tool continuity and replay semantics remain outstanding. This issue stays open.
Verified against dev
5759d9ea2f1e7281cdc01eb9628f2e0a123fb59c. Original report by @foo1maker. The attribution record was added in #3811.Client or integration
Codex App
Provider or upstream service
Ollama Cloud (
https://ollama.com/v1, key-authopenai-responsespassthrough)OpenCodex version
2.43.0 (
@bitkyc08/opencodex)Endpoint or capability
/v1/responses+ hosted{type:"web_search"}/webSearchSidecarCurrent behaviour
Codex App always speaks Responses to OpenCodex (
POST /v1/responses) and advertises the hosted tool{type:"web_search"}.For a key-auth provider with
adapter: "openai-responses"(Ollama Cloud GLM / DeepSeek, etc.) OpenCodex takes the passthrough branch insrc/server/responses/core.tsand returns beforerunWithWebSearch.planWebSearch/shouldResolveOpenAiWebSearchSidecaralso fail closed onisPassthrough:The comment assumes passthrough means ChatGPT, which already executes hosted search server-side.
Ollama Cloud does not execute OpenAI hosted
{type:"web_search"}on/v1/responses. The model instead emits a clientfunction_callnamedweb_search. Two failures follow:Stock
responses-undeclared-tool-guardtreats that echo as an undeclared client tool and aborts the SSE stream:routed provider emitted undeclared client tool "web_search"; only request-declared tools may be calledCodex App then reconnects 5/5 and the worker/turn dies (
last_agent_message: null).If the guard is relaxed, Codex App still does not execute a function named
web_search(it expects the provider to run hosted search). The next hop isunsupported call: web_search. The model can continue without live results. DashboardwebSearchSidecar(e.g. gpt-5.6-luna) stays idle.Ollama does have a working search API, but it is a separate client-executed REST endpoint, not ChatGPT hosted search:
POST https://ollama.com/api/web_searchOfficial OpenCodex backends (
openai/anthropic/xai/gemini/exa) never call it. The sidecar loop that would intercept a syntheticweb_searchfunction tool never runs on this passthrough path.Switching the provider to
openai-chatwould enter the sidecar loop, but Codex App cannot be switched off Responses, and translating GLM/DeepSeek off/v1/responsesdrops reasoning summaries and the native tool surface that this client requires.Expected behaviour
On key-auth Responses passthrough to a gateway that does not execute OpenAI hosted
web_search:function_callnamedweb_searchwhen the request catalog already declared hosted{type:"web_search"}(same catalog entry, different wire shape).function_call_output(and/or a hostedweb_search_callitem Codex understands).POST /api/web_searchwhen the route is Ollama Cloud (same credential, no ChatGPT sidecar spend). Luna/Exa remain valid fallbacks for translated routes, which is the current sidecar design.Passthrough should keep meaning “preserve the Responses wire”, not “the upstream is ChatGPT and already searched”.
Minimal redacted request or reproduction
{ "defaultProvider": "ollama-relay", "webSearchSidecar": { "enabled": true }, "providers": { "ollama-relay": { "adapter": "openai-responses", "baseUrl": "https://ollama.com/v1", "authMode": "key", "selectedModels": ["glm-5.3-flash"] }, "openai": { "adapter": "openai-responses", "baseUrl": "https://chatgpt.com/backend-api/codex", "authMode": "forward" } } }ocx start(2.43.0 stock).unsupported call: web_searchwith no sidecar / noPOST https://ollama.com/api/web_search.Actual response or error
If that guard is bypassed, the Codex client hop is:
Upstream GLM item shape (redacted):
{ "type": "function_call", "name": "web_search", "arguments": "{\"query\":\"site:example.com current pricing\"}" }OpenCodex logs show no
[web-search]sidecar enter on these turns. Ollama/api/web_searchis not requested.Upstream documentation
/v1/responsesis non-stateful; hosted ChatGPTweb_searchis not listed as provider-executed): https://docs.ollama.com/api/openai-compatibilityweb_searchtool (what Codex App sends): https://platform.openai.com/docs/guides/tools-web-searchSuggested mapping or implementation notes
Stock code already has the intercept loop for translated adapters (
runWithWebSearch+buildWebSearchTool). The gap is thatadapter.passthroughboth:planWebSearch(..., isPassthrough)/ early return incore.ts), and{type:"web_search"}unchanged, which Ollama echoes as a namedfunction_call.A minimal passthrough-aware path:
addNamelessClientCallTypes, treat hostedweb_search/web_search_previewas authorizing a clientfunction_callnamedweb_search(same catalog, echo shape). This at least stops Mode 2 / App workers from 5/5-dying.authMode: "key") passthrough SSE, interceptfunction_callname === "web_search", run an executor, hide the synthetic call from Codex, inject the tool result into the next upstream hop.ollamaweb-search backend that POSTshttps://ollama.com/api/web_searchwith the existing provider key. Keep luna foropenai-chat/ Anthropic routes.Do not require operators to change Codex App to Chat Completions. The App wire is Responses; Ollama Cloud also speaks
/v1/responses. The missing piece is executing search for that pair.Additional context
Searched existing issues. Closest prior art is passthrough tool-surface gaps (e.g. #1950 tool_search rewrite on Responses passthrough) and web-search sidecar bugs on translated openai-chat routes (#265, #1001). I did not find an open issue for Ollama Cloud hosted-
web_searchecho vs/api/web_search.Related but separate: Ollama
/v1/responsesalso lacksprevious_response_idstore (documented).statelessResponsesaddresses replay; it does not execute search.Checks