Skip to content

fix(openai/responses): preserve OpenRouter server tools (openrouter:web_search) in filterUnsupportedTools - #4532

Merged
akshaydeo merged 6 commits into
maximhq:devfrom
abdenasseraroukhsiss:fix/responses-preserve-openrouter-server-tools
Jun 21, 2026
Merged

akshaydeo merged 6 commits into
maximhq:devfrom
abdenasseraroukhsiss:fix/responses-preserve-openrouter-server-tools

Conversation

@abdenasseraroukhsiss

Copy link
Copy Markdown
Contributor

What

filterUnsupportedTools (core/providers/openai/responses.go) strips any tool whose type is not in the OpenAI-native whitelist. OpenRouter server tools (openrouter:web_search) are not in that whitelist, so for provider=openrouter on /v1/responses the tool is dropped: the upstream OpenRouter call runs with tools: [], no web search executes, and with tool_choice: "required" the upstream returns 400.

Fixes #4530.

Change

Mirror the existing xAI x_search handling: when provider == OpenRouter, allow the OpenRouter-native openrouter:web_search server tool through the filter. Adds the ResponsesToolTypeOpenRouterWebSearch constant.

Repro (before this change)

A direct OpenRouter call runs the tool and returns url_citation annotations; the same request routed through Bifrost drops the tool and returns no citations. Full curl repro in #4530.

Test

TestToOpenAIResponsesRequest_OpenRouterServerToolPreserved asserts openrouter:web_search is preserved for provider=openrouter and stripped for provider=openai.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 34933468-948b-4829-8b02-82d493fe9f32

📥 Commits

Reviewing files that changed from the base of the PR and between 763436f and a855fd7.

📒 Files selected for processing (1)
  • core/providers/openai/responses_test.go

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • OpenRouter server-side tools using the openrouter: namespace are now preserved during API request conversions instead of being filtered out.
  • Tests

    • Added unit test coverage to confirm OpenRouter tools (e.g., openrouter:web_search, openrouter:web_fetch) are retained, while non-OpenRouter namespaced tools are filtered as expected.
  • Documentation

    • Documented and introduced the openrouter: tool namespace prefix constant for clearer tool-type handling.

Walkthrough

Adds a new ResponsesToolTypeOpenRouterPrefix constant ("openrouter:") to define the OpenRouter tool namespace, then extends filterUnsupportedTools to whitelist any tool type with that prefix when the request provider is schemas.OpenRouter. A new test verifies that OpenRouter-namespaced tools are preserved for OpenRouter and stripped for OpenAI.

Changes

OpenRouter server tools namespace whitelist

Layer / File(s) Summary
OpenRouter namespace constant and filter whitelist
core/schemas/responses.go, core/providers/openai/responses.go
ResponsesToolTypeOpenRouterPrefix ("openrouter:") constant is introduced. filterUnsupportedTools is extended to allow any tool whose Type starts with that prefix when provider == schemas.OpenRouter, broadening support to all future OpenRouter server tools instead of hardcoding individual types.
Test validation across providers
core/providers/openai/responses_test.go
New test asserts that openrouter:web_search and openrouter:web_fetch survive conversion for OpenRouter and are removed for OpenAI, using a test helper to build requests with single tools.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • maximhq/bifrost#3976: Modifies the same filterUnsupportedTools function in core/providers/openai/responses.go using the same pattern of provider-conditional tool whitelisting (for xAI x_search).

Suggested reviewers

  • akshaydeo
  • danpiths
  • roroghost17

Poem

🐇 The rabbit opens the namespace gate wide,
openrouter: tools now pass with pride!
No more hardcoding, the prefix leads the way,
All OpenRouter server tools here to stay.
Three files, a prefix, the future is bright,
The tool filter's now... just right! 🌐

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and clearly describes the main fix: preserving OpenRouter server tools in the filterUnsupportedTools function.
Description check ✅ Passed The PR description explains the problem, root cause, and solution, though it lacks explicit sections for how to test and verification steps.
Linked Issues check ✅ Passed Code changes directly address issue #4530: added prefix-based filtering for openrouter: tools, introduced ResponsesToolTypeOpenRouterPrefix constant, and added test validating openrouter:web_search is preserved for OpenRouter provider.
Out of Scope Changes check ✅ Passed All changes (filterUnsupportedTools logic, constant definition, and test) directly support the objective of preserving OpenRouter server tools with no extraneous modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

Safe to merge — the change is narrowly scoped to a two-condition guard inside filterUnsupportedTools and does not touch any other provider path.

The fix is a minimal, targeted change: a prefix check gated on Provider == OpenRouter that prevents valid OpenRouter server tools from being silently discarded. The normalizeResponsesToolType path in schema deserialization leaves openrouter:* strings unchanged, so the tool type arriving at the filter is exactly what the guard expects. The new test exercises both the preserve and strip paths, including two different openrouter: tool types. No other provider, streaming path, or shared data structure is touched.

No files require special attention.

Important Files Changed

Filename Overview
core/providers/openai/responses.go Adds an isOpenRouterServerTool guard using prefix matching on openrouter: to preserve OpenRouter server tools from being stripped by filterUnsupportedTools; correctly gated on Provider == OpenRouter and does not affect any other provider path.
core/schemas/responses.go Adds ResponsesToolTypeOpenRouterPrefix = "openrouter:" constant; normalizeResponsesToolType correctly leaves openrouter:* strings unchanged (none of its prefix cases match the openrouter: namespace).
core/providers/openai/responses_test.go New test correctly covers both the preserve (OpenRouter provider) and strip (OpenAI provider) cases using two tool types; passes nil as the ctx parameter matching the function signature.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[filterUnsupportedTools] --> B{len tools == 0?}
    B -- yes --> Z[return]
    B -- no --> C[build supportedTypes whitelist]
    C --> D{Provider == xAI?}
    D -- yes --> E[add x_search to whitelist]
    D -- no --> F
    E --> F[iterate tools]
    F --> G{supportedTypes tool.Type ?}
    G -- yes --> I[append tool]
    G -- no --> H{Provider == OpenRouter AND HasPrefix openrouter: ?}
    H -- yes --> I
    H -- no --> J[drop tool]
    I --> K[next tool]
    J --> K
    K --> F
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[filterUnsupportedTools] --> B{len tools == 0?}
    B -- yes --> Z[return]
    B -- no --> C[build supportedTypes whitelist]
    C --> D{Provider == xAI?}
    D -- yes --> E[add x_search to whitelist]
    D -- no --> F
    E --> F[iterate tools]
    F --> G{supportedTypes tool.Type ?}
    G -- yes --> I[append tool]
    G -- no --> H{Provider == OpenRouter AND HasPrefix openrouter: ?}
    H -- yes --> I
    H -- no --> J[drop tool]
    I --> K[next tool]
    J --> K
    K --> F
Loading

Reviews (5): Last reviewed commit: "test case fixes" | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/providers/openai/responses.go`:
- Around line 341-343: The current implementation only allowlists
ResponsesToolTypeOpenRouterWebSearch for OpenRouter providers (lines 341-343),
but OpenRouter supports 6 server-side tools with the openrouter: prefix. Instead
of checking for individual tool type constants that don't exist for the other 5
tools, replace the explicit tool type check with a namespace-based prefix match
that identifies any tool starting with openrouter: and adds it to
supportedTypes. This approach will capture all current and future OpenRouter
tools (web_search, web_fetch, datetime, image_generation, apply_patch, subagent)
and prevent them from being silently stripped by the whitelist validation logic.
Additionally, add test coverage for at least one non-web_search OpenRouter tool
to ensure the namespace prefix matching works correctly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 23fd0ac7-527b-4a30-952f-041bcf73be50

📥 Commits

Reviewing files that changed from the base of the PR and between 96bb2bd and 087bf22.

📒 Files selected for processing (3)
  • core/providers/openai/responses.go
  • core/providers/openai/responses_test.go
  • core/schemas/responses.go

Comment thread core/providers/openai/responses.go Outdated
@abdenasseraroukhsiss
abdenasseraroukhsiss force-pushed the fix/responses-preserve-openrouter-server-tools branch from 087bf22 to 0d1397d Compare June 18, 2026 14:18
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 18, 2026
@CLAassistant

CLAassistant commented Jun 21, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 21, 2026
Comment thread core/providers/openai/responses_test.go Outdated
Comment thread core/providers/openai/responses_test.go Outdated
@akshaydeo
akshaydeo force-pushed the fix/responses-preserve-openrouter-server-tools branch from 51cc564 to 2b17bf8 Compare June 21, 2026 07:07
sammaji and others added 4 commits June 21, 2026 12:38
…pportedTools

filterUnsupportedTools stripped tools whose type was not in the OpenAI-native
whitelist, including OpenRouter server tools (the "openrouter:" namespace:
web_search, web_fetch, datetime, image_generation, apply_patch, subagent).
For provider=openrouter on /v1/responses this dropped the tool, so the upstream
call ran with tools:[] and no server tool executed (tool_choice:"required" then
caused a 400 from the upstream).

Allow any "openrouter:"-prefixed tool type through the filter when
provider == OpenRouter, mirroring the existing XAI x_search handling. This
covers all current and future OpenRouter server tools without per-tool additions.

Fixes maximhq#4530
@akshaydeo
akshaydeo force-pushed the fix/responses-preserve-openrouter-server-tools branch from 2b17bf8 to c3a6408 Compare June 21, 2026 07:08
akshaydeo
akshaydeo previously approved these changes Jun 21, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 21, 2026
@coderabbitai
coderabbitai Bot requested a review from akshaydeo June 21, 2026 07:12
@akshaydeo
akshaydeo dismissed stale reviews from coderabbitai[bot] and themself via a855fd7 June 21, 2026 07:14
@akshaydeo
akshaydeo merged commit 90b5384 into maximhq:dev Jun 21, 2026
4 of 6 checks passed
akshaydeo added a commit that referenced this pull request Jun 21, 2026
…eb_search) in filterUnsupportedTools (#4532)

* fix(openai/responses): preserve OpenRouter server tools in filterUnsupportedTools
filterUnsupportedTools stripped tools whose type was not in the OpenAI-native
whitelist, including OpenRouter server tools (the "openrouter:" namespace:
web_search, web_fetch, datetime, image_generation, apply_patch, subagent).
For provider=openrouter on /v1/responses this dropped the tool, so the upstream
call ran with tools:[] and no server tool executed (tool_choice:"required" then
caused a 400 from the upstream).

Allow any "openrouter:"-prefixed tool type through the filter when
provider == OpenRouter, mirroring the existing XAI x_search handling. This
covers all current and future OpenRouter server tools without per-tool additions.

Fixes #4530

* removes scripts

* test case fixes

---------

Co-authored-by: akshaydeo <akshay@akshaydeo.com>
akhsaul pushed a commit to akhsaul/bifrost that referenced this pull request Aug 27, 2026
…eb_search) in filterUnsupportedTools (maximhq#4532)

* fix(openai/responses): preserve OpenRouter server tools in filterUnsupportedTools
filterUnsupportedTools stripped tools whose type was not in the OpenAI-native
whitelist, including OpenRouter server tools (the "openrouter:" namespace:
web_search, web_fetch, datetime, image_generation, apply_patch, subagent).
For provider=openrouter on /v1/responses this dropped the tool, so the upstream
call ran with tools:[] and no server tool executed (tool_choice:"required" then
caused a 400 from the upstream).

Allow any "openrouter:"-prefixed tool type through the filter when
provider == OpenRouter, mirroring the existing XAI x_search handling. This
covers all current and future OpenRouter server tools without per-tool additions.

Fixes maximhq#4530

* removes scripts

* test case fixes

---------

Co-authored-by: akshaydeo <akshay@akshaydeo.com>
occcat pushed a commit to occcat/bifrost that referenced this pull request Sep 2, 2026
…eb_search) in filterUnsupportedTools (maximhq#4532)

* fix(openai/responses): preserve OpenRouter server tools in filterUnsupportedTools
filterUnsupportedTools stripped tools whose type was not in the OpenAI-native
whitelist, including OpenRouter server tools (the "openrouter:" namespace:
web_search, web_fetch, datetime, image_generation, apply_patch, subagent).
For provider=openrouter on /v1/responses this dropped the tool, so the upstream
call ran with tools:[] and no server tool executed (tool_choice:"required" then
caused a 400 from the upstream).

Allow any "openrouter:"-prefixed tool type through the filter when
provider == OpenRouter, mirroring the existing XAI x_search handling. This
covers all current and future OpenRouter server tools without per-tool additions.

Fixes maximhq#4530

* removes scripts

* test case fixes

---------

Co-authored-by: akshaydeo <akshay@akshaydeo.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: /v1/responses strips OpenRouter server tools (openrouter:web_search) via filterUnsupportedTools

4 participants