Skip to content

feat: keep OpenAI web search queries and consulted sources - #62

Draft
mafredri wants to merge 4 commits into
coder_2_33from
mafredri/responses-web-search-queries
Draft

mafredri wants to merge 4 commits into
coder_2_33from
mafredri/responses-web-search-queries

Conversation

@mafredri

@mafredri mafredri commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Problem

coder/coder#29861 shows provider-executed OpenAI web_search calls 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.

  • WebSearchAction kept only the deprecated action.query. Current responses report action.queries, which it ignored.
  • OpenAI returns action.sources only when the request includes web_search_call.action.sources, and the provider did not request it.
  • In streams, the response.output_item.done event for a web_search_call can leave out sources entirely (gpt-4.1, now recorded in the TestOpenAIWebSearch cassette) or list only some of them (a live gpt-5-mini probe returned 36 at done and 38 in response.completed). In both cases the terminal response listed them all.

Fix

  • Add IncludeWebSearchCallActionSources and send it automatically whenever the call has a web search tool, without duplicating a caller-supplied include. Bedrock Mantle rejects this include (web_search tool unconditionally adds include: 'web_search_call.action.sources', breaking OpenAI-compatible providers (Amazon Bedrock Mantle rejects it) vercel/ai#18507), so openai.WithoutWebSearchSources() and openaicompat.WithoutWebSearchSources() turn the automatic include off; an explicit ResponsesProviderOptions.Include entry is still sent. fix(openai): allow providers to disable web search source includes vercel/ai#20599 added the same provider-level opt-out.
  • Add Queries to WebSearchAction, so the result metadata carries Queries, the deprecated Query, and Sources. Citation sources still come only from url_citation annotations.
  • In streams, emit the web_search tool result when the terminal event arrives (response.completed, response.incomplete or response.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.
  • Set the tool call input to {"queries": [...]}, falling back to [query]. The result now arrives after the answer text, so callers read the queries from the call. The queries key 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_search call 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

  • New providers/openai/responses_web_search_test.go covers streaming and non-streaming responses with queries and sources, only the deprecated query, and no queries. It also covers sources that appear only in response.completed or response.failed, a stream that ends without a terminal event, include deduplication, and WithoutWebSearchSources. providers/openaicompat/web_search_sources_test.go checks the option through openaicompat.
  • Re-recorded providertests/testdata/TestOpenAIWebSearch through a live OpenAI-compatible gateway, because the request body now carries the include. The cassette URL is https://api.openai.com/v1/responses, and the VCR hook strips auth headers.
  • go test ./... -count=1 and golangci-lint run ./providers/openai/... ./providers/openaicompat/... pass.

🤖 This PR was created with the help of Coder Agents, and will be reviewed by a human. 🏂🏻

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.
@mafredri

Copy link
Copy Markdown
Member Author

/coder-agents-review

@mafredri

Copy link
Copy Markdown
Member Author

@codex review

@mafredri
mafredri requested a balanced review from Copilot September 24, 2026 15:40
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-24T15:44:42.919296Z a7c6a7b Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 High severity

Open (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.

Comment thread providers/openai/responses_language_model.go Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread providers/openai/responses_language_model.go Outdated
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.
mafredri added a commit to coder/coder that referenced this pull request Sep 24, 2026
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.
mafredri added a commit to coder/coder that referenced this pull request Sep 24, 2026
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.
mafredri added a commit to coder/coder that referenced this pull request Sep 24, 2026
coder/fantasy#62 now adds WithoutWebSearchSources for backends that
reject web_search_call.action.sources. chatd does not set it, so
requests are unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants