[Provider compatibility] Conditional hosted-search filtering for Gemini Responses mixed with client tools
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
Research direction
Start with the hosted-tool filtering mechanism related to #5002, especially stripUnsupportedHostedTools and the provider configuration and management paths described in the issue. Trace how root tools, additional_tools catalogs, aliases, and selectors are handled, then check the existing hosted-tool and provider management tests. Done means conditional filtering preserves standalone search and ordinary tools, validates configuration, survives provider saves and PATCH clearing, and leaves undeclared-tool validation intact.
Written by the indexing model from the issue text.
Description
Client or integration
Codex App and direct HTTP client
Provider or upstream service
IkunCode OpenAI-compatible Responses endpoint, https://api.ikuncode.cc/v1/responses. Tested model IDs: gemini-4-argon and gemini-3.8-flash.
OpenCodex version
2.97.0 on macOS; source base tag v2.97.0.
Endpoint or capability
Responses hosted web_search_preview / web_search declarations combined with ordinary client function/custom tools, including namespace and client-loaded tool catalogs.
Current behaviour
The existing unsupportedHostedTools: ["web_search"] is an effective workaround for mixed-tool requests, but also removes the search-only capability that the upstream actually accepts.
Synthetic direct tests on both model IDs, 2026-11-06:
| Declared tools | Result |
|---|---|
| ordinary function only | 200, completed |
| hosted search only | 200, completed |
| hosted search + ordinary function | 400, error below |
mixed tools + top-level tool_config.include_server_side_tool_invocations=true |
same 400 |
A separate search-only request through the locally patched gateway actually emitted response.web_search_call.in_progress, searching, completed, a completed web_search_call item and URL citations. This is more than a declaration-only success.
These tests establish this endpoint's observed contract. They do not establish whether the mixed-tool limitation originates in IkunCode's conversion or Google's serving stack, and do not verify the underlying model identity.
Expected behaviour
Allow a provider to describe a conditional incompatibility: omit a named hosted declaration only when client function/custom tools are also present. Preserve standalone hosted search, preserve ordinary tools, reconcile selectors and client-loaded catalogs, and retain undeclared-tool validation. Do not silently change unrelated providers.
Minimal redacted request or reproduction
Use an existing key for the intended provider. All content below is synthetic.
curl https://api.ikuncode.cc/v1/responses \
-H "Authorization: Bearer $IKUNCODE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-4-argon",
"input": "Synthetic test. Do not search or call tools. Reply exactly OK.",
"stream": true,
"tools": [
{"type": "web_search_preview"},
{
"type": "function",
"name": "lookup_marker",
"description": "Read a synthetic diagnostic marker.",
"parameters": {
"type": "object",
"properties": {"marker": {"type": "string"}},
"required": ["marker"],
"additionalProperties": false
}
}
]
}'
Remove either tool declaration: both isolated variants complete. Replace the model ID with gemini-3.8-flash: the same matrix reproduces. Adding the requested flag at the Responses top level did not change the observed mixed-tool 400.
Actual response or error
{
"error": {
"message": "Please enable tool_config.include_server_side_tool_invocations to use Built-in tools with Function calling.",
"type": "upstream_error",
"param": "",
"code": 400
}
}
Upstream documentation
Provider metadata: https://api.ikuncode.cc/api/pricing lists the tested model IDs with Gemini and OpenAI endpoint types. It does not document this mixed-tool restriction.
Google's referenced tool-combination documentation: https://ai.google.dev/gemini-api/docs/generate-content/tool-combination . The compatibility claim here is based on the concrete synthetic matrix above, not an assumption that every OpenAI-compatible Responses gateway forwards Google's tool_config fields.
Suggested mapping or implementation notes
A tested local implementation adds an opt-in provider field:
{
"adapter": "openai-responses",
"unsupportedHostedToolsWithFunctions": ["web_search"]
}
The existing unconditional unsupportedHostedTools remains authoritative and unchanged. The new conditional policy:
- detects function/custom tools or populated namespaces in root and
additional_toolscatalogs; - expands hosted aliases through the existing policy helper;
- reuses the existing filtering and selector reconciliation;
- validates a closed hosted-tool vocabulary at config and management boundaries;
- survives same-destination provider saves, is returned by provider GET, and supports PATCH clearing;
- does not alter the undeclared-tool guard or grant Bash/other tools.
Core change in stripUnsupportedHostedTools:
const conditional = provider.unsupportedHostedToolsWithFunctions;
const catalogs = conditional?.length
? [body.tools, ...(Array.isArray(body.input) ? body.input.flatMap(item =>
isPlainObject(item) && item.type === "additional_tools" ? [item.tools] : []) : [])]
: [];
const hasFunctions = catalogs.some(tools => Array.isArray(tools) && tools.some(tool =>
isPlainObject(tool) && (tool.type === "function" || tool.type === "custom"
|| (tool.type === "namespace" && Array.isArray(tool.tools) && tool.tools.length > 0))));
const declaredUnsupported = declaredUnsupportedHostedTools(hasFunctions
? { unsupportedHostedTools: [...(provider.unsupportedHostedTools ?? []), ...conditional!] }
: provider);
A narrower provider capability is preferable to hard-coding IkunCode's URL. An upstream mixed-tool fix could later make even this opt-in unnecessary.
Additional context and attachments
Related mechanism: #5002. This request is specifically conditional filtering rather than a second unconditional deny list.
Local validation:
- 38 hosted-tool declaration tests passed, including new mixed/root/loaded/alias cases.
- 38 management carry-over and reset-policy tests passed.
- 168 undeclared-tool/inbound/model-rename tests passed.
- Typecheck passed for 2,305 source files.
- Privacy scan passed; docs build passed (641 pages).
- The broad import-graph changed-test run was interrupted after several minutes without a completed selection/result; it is not reported as passing. No full-suite result is claimed.
- Isolated and production synthetic requests passed after the local patch: mixed tool declarations, namespace custom-tool call and result continuation, and standalone hosted search with actual search events.
- Official OpenAI connectivity was checked separately; this change does not change provider/network routing.
A separate intermittent pre-output EOF/long wait has also been observed. This conditional-filtering patch is not claimed to fix all Gemini disconnects.
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.
- Dominant language
- TypeScript
- Stars
- 16.9k
- Forks
- 1.3k
- Avg merge
- 19h 24m
- Merged PRs (30d)
- 676
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from lidge-jun/opencodex
-
account-pool bug gui
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
lidge-jun/opencodex#8131 · 3 comments ·
Maintainers usually reply within 1 day
-
bug streaming
Difficulty 4/5 3-5 days Newbie friendliness 48/100
lidge-jun/opencodex#8231 · 1 comment ·
Maintainers usually reply within 1 day
-
bug streaming
Difficulty 4/5 1-2 days Newbie friendliness 48/100
lidge-jun/opencodex#8216 · 1 comment ·
Maintainers usually reply within 1 day
-
bug streaming
Difficulty 4/5 3-5 days Newbie friendliness 55/100
lidge-jun/opencodex#8206 · 1 comment ·
Maintainers usually reply within 1 day
-
sub2api codex_cli_only rejects official Codex requests after client identifiers are strippedPossibly taken A pull request linked to this issue is open or already merged. Openprovider provider-compatibility streaming
Difficulty 3/5 1-2 days Newbie friendliness 55/100
lidge-jun/opencodex#8192 · 1 comment ·
Maintainers usually reply within 1 day
All issues in lidge-jun/opencodex
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
area:ui bug effort:S priority:P2
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Typo in WSL project description on Projects pagePossibly taken @akhil9tiet claimed this today. Open
Difficulty 1/5 Under an hour Newbie friendliness 75/100
microsoft/opensource.microsoft.com#1066 · 1 comment ·
-
ArcGIS Maps SDK for JavaScript c-carousel calcite-design-tokens enhancement impact - p3 - not time sensitive needs triage
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Esri/calcite-design-system#15565 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
linkwarden/linkwarden#1891 ·
Maintainers usually reply within 1 day