Skip to content

feat(sidecar): OpenCode Zen (opencode.ai/zen/go/v1) as web-search sidecar backend — natively serves hosted web_search, no ChatGPT/Claude quota #1616

Description

@carlosqwqqwq

Area

Proxy and routing · Web-search sidecar

What are you trying to accomplish?

When the main model is routed through a third-party provider, the web-search sidecar currently has only two backends: openai (gpt-mini via the ChatGPT forward path) and anthropic (stored Claude OAuth). Both borrow an account the user may have very little quota on — and when that quota is exhausted, search turns degrade (the exact scenario from #398).

I'd like to point the web-search sidecar at a provider I actually have quota on: OpenCode Zen (https://opencode.ai/zen/go/v1, the built-in "opencode-go" provider), using e.g. deepseek-v4-flash to execute the search — with zero ChatGPT/Claude quota consumption.

What prevents this today?

  • OcxWebSearchSidecarConfig.backend is hardcoded to "openai" | "anthropic" (src/types.ts, src/web-search/index.ts resolveSidecarBackend); there is no keyed/custom-provider option.
  • The hosted web_search tool is unconditionally stripped for routed providers (src/responses/parser.ts buildTools), and the sidecar executor only knows how to POST to the ChatGPT forward endpoint with forwarded OAuth headers (src/web-search/executor.ts runWebSearch).
  • I verified there is no config-only workaround (changing webSearchSidecar.model, disabling the sidecar, or repointing the openai provider's baseUrl all fail — the latter breaks isCanonicalOpenAiForwardProvider).

Key fact: OpenCode Zen natively serves hosted web_search

Unlike a plain OpenAI-compatible chat gateway, OpenCode Zen executes the Responses API's hosted web_search tool server-side. Tested 2026-08-13 with a opencode-go API key (model deepseek-v4-flash):

  • POST https://opencode.ai/zen/go/v1/responses with tools: [{type: "web_search", max_results: 5}] + tool_choice: {type: "web_search"}200.
  • The model ran real multi-step searches (web_search_call with search and open_page actions) and returned a summary with source URLs.
  • Streaming emits standard Responses SSE — response.output_text.delta, response.output_text.done, response.completed (plus ping heartbeats) — exactly the event shapes parseSidecarSSE already handles.
  • The gateway reports "cost": "0" for these calls; either way, the spend lands on the user's Zen key, not ChatGPT/Claude.

This is the "provider-native search capability" category of #415 — Zen just isn't on the list there yet. It also fits #414's "decouple which account backs search" goal without adding a dedicated search vendor.

Proposed change (minimal, additive)

Add a third sidecar backend, e.g. backend: "keyed" with provider + model config, that POSTs to the named provider's {baseUrl}/responses with Authorization: Bearer <apiKey> and the same hosted tool + BASE_INSTRUCTION, reusing the existing loop, parseSidecarSSE, and format-result unchanged:

  • src/types.ts — extend OcxWebSearchSidecarConfig (backend: "keyed", provider?: string)
  • src/web-search/executor.ts — add runKeyedWebSearch() (~30 lines, mirrors runWebSearch with Bearer auth)
  • src/web-search/index.tsplanWebSearch keyed branch, resolving a configured key-auth openai-responses provider
  • src/web-search/loop.ts + src/server/responses/core.ts — thread the keyed provider through and dispatch

Roughly 60–80 additive lines; the ChatGPT forward path and anthropic path stay untouched.

Acceptance criteria

  • Config like webSearchSidecar: { backend: "keyed", provider: "opencode-go", model: "deepseek-v4-flash" } makes search runs on the Zen key with no ChatGPT/Claude quota involvement.
  • Search cells, citations/sources, and the loop behavior match the existing openai backend.

Related

#398 (original fixed-backend bug), #414 (dedicated search vendors like Exa), #415 (provider-native search, e.g. Gemini Grounding — Zen is a sibling case), #1276 (superseded umbrella; maintainer's note that arbitrary LLMs can't auto-back search is exactly why Zen's hosted tool is special).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

account-poolOAuth, credentials, Codex pool, quota, failover, plansenhancementNew feature or requesttoolstool_calls, MCP, web-search / sidecar tools

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions