Conversation
OpenAI now reports search queries in web_search_call action.queries and deprecated action.query. The metadata only kept query, so callers lost the queries of current responses. action.sources, the URLs a search consulted, is only returned when the request includes web_search_call.action.sources, so requests with the web_search tool now add it. When streaming, response.output_item.done can omit sources or list only some of them; response.completed carries the full list. The web_search result is now emitted at the terminal event with that action data. The TestOpenAIWebSearch cassettes were re-recorded because the request body changed; they show done items without sources.
The streamed web_search result now waits for the terminal event, so the
call emitted at output_item.done was the first signal that the search
finished, yet it carried no input. Callers could not show what was
searched until the whole answer had streamed.
The call input is now {"queries": [...]}, using the deprecated query
when queries is absent. A response.failed event also supplies its output
when flushing pending results, so its sources are kept.
|
/coder-agents-review |
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Automatic source inclusion can break Mantle-backed custom endpoints without an opt-out.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
What changed in this PR
Adds preservation of OpenAI web-search queries and consulted sources across generated and streamed responses.
Changes:
- Requests web-search source metadata automatically.
- Emits query input and terminal source metadata for tool calls.
- Adds unit/integration coverage and updates VCR cassettes.
| File | Description |
|---|---|
providers/openai/responses_language_model.go |
Handles source inclusion and web-search metadata. |
providers/openai/responses_options.go |
Adds include type and query fields. |
providers/openai/responses_web_search_test.go |
Tests generation, streaming, failures, and metadata. |
providertests/openai_web_search_test.go |
Validates integration metadata. |
providertests/testdata/TestOpenAIWebSearch/generate.yaml |
Updates generate cassette. |
providertests/testdata/TestOpenAIWebSearch/stream.yaml |
Updates streaming cassette. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a7c6a7b6eb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Remove comments that repeat field names, keep the terminal-event rationale on pendingWebSearchResults, and narrow claims about sources and the deprecated query to what recorded and live responses showed.
Fix the stale test comment that said the result carries the queries, drop comments that repeat field names, and say that Fantasy, not the provider API, keeps consulted URLs only in metadata. The pin moves to the fantasy pin branch with the matching comment cleanup from coder/fantasy#62. It has no behavior change.
Fix the stale test comment that said the result carries the queries, drop comments that repeat field names, and say that Fantasy, not the provider API, keeps consulted URLs only in metadata. The pin moves to the fantasy pin branch with the matching comment cleanup from coder/fantasy#62. It has no behavior change.
Bedrock Mantle rejects web_search_call.action.sources, and the provider added it to every Responses request with a web search tool, so web search against such backends failed with no workaround. The option turns off the automatic include for openai and openaicompat; an explicit ResponsesProviderOptions.Include entry is still sent.
coder/fantasy#62 now adds WithoutWebSearchSources for backends that reject web_search_call.action.sources. chatd does not set it, so requests are unchanged.

Problem
coder/coder#29861 shows provider-executed OpenAI
web_searchcalls in the Coder Agents UI and needs two things from them: what was searched and which URLs the search consulted. The Responses provider dropped both.WebSearchActionkept only the deprecatedaction.query. Current responses reportaction.queries, which it ignored.action.sourcesonly when the request includesweb_search_call.action.sources, and the provider did not request it.response.output_item.doneevent for aweb_search_callcan leave outsourcesentirely (gpt-4.1, now recorded in theTestOpenAIWebSearchcassette) or list only some of them (a live gpt-5-mini probe returned 36 atdoneand 38 inresponse.completed). In both cases the terminal response listed them all.Fix
IncludeWebSearchCallActionSourcesand send it automatically whenever the call has a web search tool, without duplicating a caller-supplied include. Bedrock Mantle rejects this include (web_searchtool unconditionally addsinclude: 'web_search_call.action.sources', breaking OpenAI-compatible providers (Amazon Bedrock Mantle rejects it) vercel/ai#18507), soopenai.WithoutWebSearchSources()andopenaicompat.WithoutWebSearchSources()turn the automatic include off; an explicitResponsesProviderOptions.Includeentry is still sent. fix(openai): allow providers to disable web search source includes vercel/ai#20599 added the same provider-level opt-out.QueriestoWebSearchAction, so the result metadata carriesQueries, the deprecatedQuery, andSources. Citation sources still come only fromurl_citationannotations.web_searchtool result when the terminal event arrives (response.completed,response.incompleteorresponse.failed) and take its action data from that event's output. If the stream ends without a terminal event, the provider still emits the result before any stream error, so every call keeps its result.{"queries": [...]}, falling back to[query]. The result now arrives after the answer text, so callers read the queries from the call. Thequerieskey is always present, so callers can tell this input from Anthropic's{"query"}, which the Anthropic provider emits before its search runs.Replay is unchanged. The Responses prompt builder still sends a provider-executed
web_searchcall only as an item reference, or not at all, and skips its result, so neither the new call input nor the result metadata reaches OpenAI.Validation
providers/openai/responses_web_search_test.gocovers streaming and non-streaming responses with queries and sources, only the deprecated query, and no queries. It also covers sources that appear only inresponse.completedorresponse.failed, a stream that ends without a terminal event, include deduplication, andWithoutWebSearchSources.providers/openaicompat/web_search_sources_test.gochecks the option throughopenaicompat.providertests/testdata/TestOpenAIWebSearchthrough a live OpenAI-compatible gateway, because the request body now carries the include. The cassette URL ishttps://api.openai.com/v1/responses, and the VCR hook strips auth headers.go test ./... -count=1andgolangci-lint run ./providers/openai/... ./providers/openaicompat/...pass.