| # Provider-hosted web search capability |
| |
| Status: implemented for OpenAI Responses and Anthropic Messages |
| `web_search_20250305`; other provider-native wires remain explicit follow-ups. |
| Verified against public provider documentation and shipped client/SDK behavior |
| on 2026-08-04. |
| |
| ## Problem |
| |
| Maka originally exposed only a Tavily-backed `WebSearch` tool. That made live |
| search require a second credential even when the selected model provider already |
| offered a server-side search tool. |
| |
| The missing abstraction was not another search-provider enum entry. Hosted |
| search depends on all three of: |
| |
| 1. the configured provider access path; |
| 2. the exact selected model; |
| 3. a provider-specific protocol and tool shape. |
| |
| `functionCalling: true` does not imply hosted search. OpenAI-compatible chat |
| does not imply Responses `web_search`, and Anthropic-compatible messages do not |
| imply support for `web_search_20250305`. |
| |
| ## Current routing |
| |
| The user chooses one explicit search source: |
| |
| - `model`: reuse the current session model connection and credential; |
| - `tavily`: use the separately configured Tavily credential. |
| |
| There is no silent fallback. If `model` is selected and the exact provider/model |
| pair is unsupported, Maka omits the native tool from that turn. Tavily remains |
| an explicit alternative rather than taking over after a failed native call. |
| |
| The capability decision lives in |
| `packages/core/src/model-web-search.ts`. Stored model metadata can explicitly |
| set `capabilities.webSearch`; otherwise narrow provider/model rules apply. |
| |
| The implemented native adapters are: |
| |
| - `openai-responses` for Codex-style `web_search`; |
| - `anthropic-messages` for Claude Code-compatible `web_search_20250305`. |
| |
| ## Execution surfaces |
| |
| All production `AiSdkBackend` composition roots use the same |
| `routeWebSearchTools` decision: |
| |
| | Surface | Configuration authority | Root behavior | |
| | --- | --- | --- | |
| | Desktop | persisted `webSearch.enabled/defaultProvider` settings | May add provider-native `WebSearch` | |
| | CLI / TUI / `maka run` | the same persisted settings | May add provider-native `WebSearch` | |
| | Runtime Host | runtime-policy web-search settings | May add provider-native `WebSearch` | |
| | Headless Harbor | explicit `MAKA_WEB_SEARCH_ENABLED=true` | May add provider-native `WebSearch` | |
| |
| Headless remains opt-in because silently enabling network search would change |
| benchmark semantics and historical baselines. Merely speaking Anthropic |
| Messages is not enough to infer hosted-search support; Maka uses explicit model |
| metadata or narrow model-id rules, including DeepSeek V4 Flash on an |
| `anthropic-compatible` connection. |
| |
| An explicit `BackendFactoryContext.tools` list is a hard ceiling. Root surfaces |
| may add native search, but scoped child agents do not gain it unless their |
| supplied tool list already contains `WebSearch`. Dedicated model experiments |
| and auxiliary calls such as title generation, history compaction, goal judging, |
| connection tests, and daily review do not receive search implicitly. |
| |
| Privacy mode removes both provider-native and client-executed `WebSearch` |
| before the model request is built. |
| |
| The built-in `web_research` child profile is derived from that same routed |
| per-session child tool surface. It is not advertised when search is disabled, |
| privacy mode is active, or the selected provider/model wire is unsupported. |
| |
| ```text |
| turn-start tool surface |
| -> provider/model capability resolution |
| -> replace client WebSearch with provider-native WebSearch |
| -> primary model POST /responses |
| tools: [{ type: "web_search" }] |
| -> provider-executed search call/result |
| -> same model stream continues to final text |
| ``` |
| |
| The search request uses the existing model credential. It does not duplicate the |
| secret into web-search settings, start a nested model request, or expose the |
| secret to the renderer. Provider search call/results are marked |
| `providerExecuted`, preserved separately from local ToolRuntime execution, and |
| replayed through the native provider-tool shape. |
| |
| The durable event keeps normalized `result` data for the canonical read model, |
| UI, and exports, plus opaque `providerOutput` data for provider-protocol replay. |
| Anthropic replay places `server_tool_use` and `web_search_tool_result` in the |
| same assistant message. Responses replay uses a provider item reference and |
| never emits an orphan `function_call_output`. |
| |
| Context budgeting measures the opaque replay payload rather than the smaller |
| display projection. Provider-native results are not partially archived: history |
| compaction removes the complete old turn instead of archiving only `result` |
| while accidentally retaining an unbounded `providerOutput`. |
| |
| DeepSeek live verification on 2026-08-04 completed one real Maka `AiSdkBackend` |
| turn with two provider-executed WebSearch calls and a final answer in the same |
| stream. DeepSeek returned search actions but no structured source rows or URL |
| annotations in that response, so Maka preserves citations when supplied but |
| does not synthesize or invent them. |
| |
| The same key was also verified through DeepSeek's Anthropic-compatible endpoint: |
| one real Maka turn sent `web_search_20250305`, received one provider-executed |
| WebSearch result containing ten source rows, and completed the final answer |
| without a second model call. This pins both the Codex/Responses and Claude |
| Code/Messages wire formats against live provider behavior. |
| |
| Full production-surface smoke verification on 2026-08-04 then ran: |
| |
| - `maka run` through a persisted DeepSeek Responses connection; |
| - `maka run` through a persisted DeepSeek Anthropic-compatible connection; |
| - Headless Harbor with Responses and `MAKA_WEB_SEARCH_ENABLED=true`; |
| - Headless Harbor with Anthropic Messages and the same explicit opt-in. |
| |
| All four runs completed with provider-executed WebSearch call/result pairs, |
| final model text, no local ToolRuntime execution of `WebSearch`, and durable |
| runtime events. Both headless runs also persisted token summaries. The |
| Responses CLI turn emitted search plus page-open actions; the Anthropic CLI |
| turn returned ten structured source rows. |
| |
| After review fixes, local HTTP wire conformance also verified second-turn |
| replay through the real AI SDK provider converters for both protocols. A later |
| live-provider rerun on 2026-08-04 timed out before either provider returned its |
| first model event, so it did not replace the earlier successful live smoke or |
| the deterministic second-turn wire tests. |
| |
| ## Dual-wire selection |
| |
| Native search never switches protocol independently from the primary model |
| request. The selected connection wire is authoritative: |
| |
| - an OpenAI Responses session receives `openai.web_search`; |
| - an Anthropic Messages session receives `anthropic.web_search_20250305`. |
| |
| For a provider that supports both, an explicit connection/model `apiProtocol` |
| wins. An ambiguous standard DeepSeek V4 Flash connection defaults to Responses; |
| using the CC wire requires an explicit Anthropic-compatible connection. Maka |
| does not retry a failed native search over the other protocol. |
| |
| A single same-prompt DeepSeek V4 Flash comparison on 2026-08-04 observed: |
| |
| | Wire | Latency | Search calls | Visible source rows | Tokens | Estimated cost | |
| | --- | ---: | ---: | ---: | ---: | ---: | |
| | Responses | 9.46 s | 2 | 0 | 5,943 | $0.00046 | |
| | Anthropic Messages | 3.13 s | 1 | 10 | 9,638 | $0.00134 | |
| |
| This is a smoke comparison, not a latency benchmark. It shows the trade-off: |
| the CC wire provided stricter `maxUses`, lower observed latency, and structured |
| source rows; Responses used much more cache, cost about one third as much, and |
| matched the general Codex/coding-agent wire. The default therefore remains |
| Responses, while the Anthropic-compatible route stays an explicit choice for |
| search-heavy workflows that value source visibility over cache economics. |
| |
| ## Provider matrix |
| |
| | Provider or access path | Official hosted search surface | Model boundary | Maka state | |
| | --- | --- | --- | --- | |
| | DeepSeek | Responses `web_search`, server-executed | `deepseek-v4-flash`; DeepSeek documents V4 Pro as not yet supported by Responses | Integrated through `openai-responses` | |
| | OpenAI API | Responses `web_search` tool | Maka currently enables the native path for GPT-5 families, whose runtime wire is already Responses | Integrated through `openai-responses` | |
| | Custom Responses relay | Responses `web_search` tool when explicitly declared by model metadata | `openai-responses-compatible` connections with `apiProtocol=openai-responses` and `capabilities.webSearch=true` | Integrated through `openai-responses` | |
| | xAI API / OAuth | Responses Agent Tools `web_search` | Maka currently enables the verified Grok 4.5 Responses route | Integrated through `openai-responses` | |
| | Alibaba Model Studio | Responses `web_search` | Qwen 3.5 Plus/Flash provider support is recorded | Provider supports it; Maka Responses adapter pending | |
| | Anthropic / Claude subscription | Messages `web_search_20250305` | Current Claude Opus/Sonnet/Haiku/Fable families | Integrated through `anthropic-messages` | |
| | MiniMax API / Coding Plan | Anthropic-compatible `web_search_20250305` | MiniMax M2.7/M3 families | Integrated through `anthropic-messages`; live provider verification pending | |
| | Google Gemini | Gemini API grounding with Google Search | Supported Gemini 2.0+ model families vary by release | Provider supports it; Maka adapter pending | |
| | Z.AI / GLM Coding Plan | Chat tool and standalone Web Search API | GLM model/tool availability varies by endpoint | Provider supports it; Maka adapter pending | |
| | Mistral | Agents/Conversations `websearch` connector | Agent-capable models | Provider supports it; Maka adapter pending | |
| | Groq | Compound systems with built-in web search | `groq/compound` and `groq/compound-mini` | Provider supports it; Maka adapter pending | |
| | OpenRouter | Web plugin and `:online` variants | Depends on routed model/plugin support | Provider supports it; Maka adapter pending | |
| | Moonshot API | No general model-API hosted search contract found | Kimi Code exposes `SearchWeb`, but that is a managed coding-platform tool | Not treated as Moonshot model capability | |
| | Cohere, Together, Fireworks, SiliconFlow | No general hosted-search contract found in the reviewed API docs | Client tools or external search remain required | Use Tavily or another future external provider | |
| |
| ## Official references |
| |
| - DeepSeek Responses compatibility: |
| https://api-docs.deepseek.com/guides/responses_api |
| - DeepSeek Anthropic compatibility: |
| https://api-docs.deepseek.com/guides/anthropic_api/ |
| - OpenAI web search: |
| https://developers.openai.com/api/docs/guides/tools-web-search |
| - Anthropic web search: |
| https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool |
| - Gemini grounding with Google Search: |
| https://ai.google.dev/gemini-api/docs/google-search |
| - xAI search tools: |
| https://docs.x.ai/developers/tools/search-tools |
| - Alibaba Qwen web search: |
| https://www.alibabacloud.com/help/en/model-studio/web-search |
| - Z.AI web search: |
| https://docs.bigmodel.cn/cn/guide/tools/web-search |
| - Mistral websearch connector: |
| https://docs.mistral.ai/agents/tools/built-in/websearch |
| - Groq web search: |
| https://console.groq.com/docs/web-search |
| - OpenRouter web search: |
| https://openrouter.ai/docs/guides/features/plugins/web-search |
| |
| ## Follow-up adapters |
| |
| Add adapters in this order: |
| |
| 1. Add an opt-in `web_search_20260209` capability for Anthropic deployments |
| that support dynamic filtering; retain `20250305` as the compatibility |
| baseline used by Claude Code and third-party Anthropic-compatible services. |
| 2. Gemini grounding with Google Search. |
| 3. Z.AI native model tool. Keep its standalone Search API outside the |
| provider-native path. |
| 4. OpenRouter web plugin. |
| 5. Mistral Agents and Groq Compound, after defining their cost and result-row |
| projection contracts. |
| |
| Every adapter must execute in the primary model request, preserve provider tool |
| events and citation metadata, keep credential isolation, and retain explicit |
| no-fallback behavior. |