Repository navigation
Description
[Bug] websearch tool is never exposed to custom/local providers (hardcoded provider whitelist in ToolRegistry)
Environment
- OpenCode Desktop 1.18.21, Windows 11
- Custom provider: Ollama via
@ai-sdk/openai-compatible(baseURL: http://localhost:11434/v1) - Models tested:
qwen3.6:35b-a3b-q4_K_M,nemotron-3.5-lightning— both have native tool calling (verified directly against Ollama's OpenAI-compatible API: they emit validtool_callsfor a websearch-like tool schema, both streaming and non-streaming)
Summary
The websearch tool is silently stripped from the tool list for any provider that is not opencode / opencode-go, unless undocumented experimental env flags are set. Custom providers (Ollama, LM Studio, llama.cpp, anything @ai-sdk/openai-compatible) therefore never receive the tool, regardless of model capabilities.
The model itself reports the confusion perfectly:
"I don't have a 'websearch' tool specifically among my available tools. I have: webfetch (requires URL), bash"
Evidence
MITM capture of the exact POST /v1/chat/completions payload that opencode sends to the local model (full sanitized captures: https://gist.github.com/4ebuRushka/06975027c42db32692fd0c2465dcca13).
Before workaround — 11 tools, no websearch:
{
"model": "qwen3.6:35b-a3b-q4_K_M",
"tool_count": 11,
"tools": ["bash", "edit", "glob", "grep", "question", "read", "skill", "task", "todowrite", "webfetch", "write"],
"websearch_present": false
}Identical list for nemotron-3.5-lightning.
After setting OPENCODE_ENABLE_EXA=true — 12 tools, websearch present, and the local model successfully calls it (3 consecutive calls within one session, keyless Exa backend):
{
"model": "qwen3.6:35b-a3b-q4_K_M",
"tool_count": 12,
"tools": ["bash", "edit", "glob", "grep", "question", "read", "skill", "task", "todowrite", "webfetch", "websearch", "write"],
"websearch_present": true
}Code path
ToolRegistry.tools filter:
const filtered = (yield* all()).filter((tool) => {
if (tool.id === WebSearchTool.id) {
return webSearchEnabled(input.providerID, { exa: flags.enableExa, parallel: flags.enableParallel });
}
// ...
});
function webSearchEnabled(providerID, flags = { exa: false, parallel: false }) {
return providerID === ID.opencode
|| providerID === ID.make("opencode-go")
|| flags.exa
|| flags.parallel;
}Flags originate from env vars: OPENCODE_ENABLE_EXA / OPENCODE_EXPERIMENTAL_EXA / OPENCODE_ENABLE_PARALLEL / OPENCODE_EXPERIMENTAL_PARALLEL; deterministic backend selection via OPENCODE_WEBSEARCH_PROVIDER=exa|parallel.
Full sanitized captures (before/after)
{
"_comment": "Sanitized MITM captures of POST /v1/chat/completions payloads sent by OpenCode Desktop 1.18.21 to a local Ollama instance. Only structural fields are preserved; message contents removed.",
"captures": [
{
"phase": "before workaround (no env flags set)",
"model": "qwen3.6:35b-a3b-q4_K_M",
"provider": "ollama_local (@ai-sdk/openai-compatible)",
"max_tokens": 32000,
"stream": true,
"tool_choice": "auto",
"tool_count": 11,
"tools": ["bash", "edit", "glob", "grep", "question", "read", "skill", "task", "todowrite", "webfetch", "write"],
"websearch_present": false
},
{
"phase": "before workaround (no env flags set)",
"model": "nemotron-3.5-lightning",
"provider": "ollama_local (@ai-sdk/openai-compatible)",
"max_tokens": 32000,
"stream": true,
"tool_choice": "auto",
"tool_count": 11,
"tools": ["bash", "edit", "glob", "grep", "question", "read", "skill", "task", "todowrite", "webfetch", "write"],
"websearch_present": false
},
{
"phase": "after OPENCODE_ENABLE_EXA=true + OPENCODE_WEBSEARCH_PROVIDER=exa (full app restart)",
"model": "qwen3.6:35b-a3b-q4_K_M",
"provider": "ollama_local (@ai-sdk/openai-compatible)",
"max_tokens": 32000,
"stream": true,
"tool_choice": "auto",
"tool_count": 12,
"tools": ["bash", "edit", "glob", "grep", "question", "read", "skill", "task", "todowrite", "webfetch", "websearch", "write"],
"websearch_present": true,
"observed_behavior": {
"model_called_websearch": true,
"websearch_executions_in_session": 3,
"exa_api_key_required": false,
"note": "assistant turn contained valid tool_call for websearch followed by three tool-result messages"
}
}
]
}- Local / custom-provider models cannot search the web at all, even when explicitly instructed to use websearch. They either answer from memory (hallucinating current data) or attempt awkward
webfetchworkarounds. - Confusing UX: docs/UI imply the tool exists; the model truthfully says it doesn't.
- A user-side plugin overriding the tool description ("use this FIRST for any search") makes local models try to comply with an instrument they don't have.
Reproduction
- Configure a custom provider (e.g., Ollama via
@ai-sdk/openai-compatible) with a tool-capable model - Ask something requiring fresh data, explicitly mentioning the websearch tool
- Model reports it has no such tool; capturing the outgoing request confirms
toolslacks websearch - Set
OPENCODE_ENABLE_EXA=true, fully restart opencode → websearch appears intoolsand works end-to-end
Expected behavior
websearch is a client-side, provider-independent tool backed by Exa/Parallel MCP. It should be available to all providers by default, or at least be configurable per provider (e.g., a config option) instead of a hardcoded whitelist plus undocumented env flags.
Related:
- websearch tool missing on Go models unless undocumented env var is set #40568 / websearch tool hidden when using the official OpenCode Go (opencode-go) provider #42378 — the same whitelist problem for the
opencode-goprovider; resolved by adding yet another entry to the whitelist instead of addressing the root cause - Add websearch provider selection to settings UI / config instead of only env var #40028 — feature request to manage websearch via config/UI instead of undocumented env vars
- tools: websearch unexpectedly switches between Exa and Parallel providers #39121 — websearch unexpectedly switches between Exa and Parallel providers
- [FEATURE]: Firecrawl web search + web fetch provider #32600 — Firecrawl as an additional keyless search provider
Activity
sahiljagtap08 commentedon Aug 23, 2026
Opened #44343. It makes a pinned OPENCODE_WEBSEARCH_PROVIDER=exa or parallel also enable the tool, so custom and local providers get websearch with one documented env var. Defaults are unchanged for everyone else, and the tools doc now covers it.
santhiprakash commentedon Aug 23, 2026
Found an existing open PR (#44343) that already addresses this issue, so I’m stepping aside to avoid duplicate work. I have a source-based alternative ready locally if it’s ever needed, but the env-pin approach in #44343 looks reasonable.
fix(websearch): make the websearch tool available to all providers
thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊