Recipes

Replace Brave WebSearch with native provider search and MCP servers in the Robota agent SDK

Discovered from README cross-links · today

Research & KnowledgeSoftware & DevOps

Rip out the vendor web-search tool; wire native provider search plus

What they did

The author removed the SDK's vendor-backed web search entirely and replaced it with two channels. First, model-native search became a provider construction option: provider definitions declare `IProviderDefinition.nativeWebTools`, an Anthropic profile enables it via `options.nativeWebTools.webSearch`, and the CLI's single `productProviderDefinitions()` turns it on by default unless a profile overrides it. Session-level switching (`IAIProvider.configureNativeWebTools`) was deleted. Second, MCP servers: on first interactive start the CLI asks once whether to add Exa (https://mcp.exa.ai/mcp) or Parallel (https://mcp.parallel.ai/mcp) or skip; the choice is written to `settings.json` `mcpServers` and approved in the same store `/mcp approve` uses, before MCP definitions resolve, so it connects that session. `robota mcp add <exa|parallel|name https-url>` does the same later. The `WebSearch` tool, `IWebSearchProvider`, the Brave adapter, `webSearchTool`, `createWebSearchTool`, `createBraveSearchProvider`, and the `retrievalAdapter`/`computerDriver` options were removed with no compatibility path. Along the way a real bug surfaced: `agent-mcp` schema narrowing kept keywords outside the universal subset (`minLength`, `maxLength`), so the session record's strict decoder rejected persisted tool schemas and every turn failed with `Session record cannot be updated: corrupt` once Exa connected. Narrowed nodes now hold only `IParameterSchema` keywords, dropping uncheckable constraints with a report and annotations quietly. An external prerequisite was handled: `@robota-sdk/[email protected]` imported `webSearchTool`, so its `web-search` DAG node was removed, 0.0.2 published, and pinned here.

How it went

Build, typecheck, lint, deps:check and the full test suite pass at the pinned commits. A real keyless MCP run connected Exa (`exa__web_search_exa`, `exa__web_fetch_exa`) and Parallel (`parallel__web_search`, `parallel__web_fetch`, `parallel__web_decisions`) as approved, and real search calls returned results. A source-CLI PTY run (replay provider, real MCP traffic, disposable HOME) confirmed: first start prompts and adds Exa, `/mcp` shows it approved, a turn completes, `mcp add parallel` refuses without a TTY and writes nothing, succeeds in a PTY, and the second start skips the question. Exit codes 0/1 as expected.

Worth knowing

Startup prints honest narrowing diagnostics for these servers (Exa: `.query.minLength`, `.objective.minLength`, `.objective.maxLength`; Parallel: `maxLength` on two fields plus `$ref`/property-count constraints on `web_decisions`) because the universal subset does not enforce string length or property-count constraints locally — the servers still enforce them. The first-start question only runs in interactive TTY modes, never for print/goal/serve/`mcp serve`/ACP. The PTY run used a replay provider with a dummy Anthropic profile, so no real model call exercised native search end to end.

Wiring

Order: (1) delete the WebSearch tool, `IWebSearchProvider`, Brave adapter and factory exports, and the `retrievalAdapter`/`computerDriver` options from `createDefaultTools` and the session; update framework, ACP mapping, apps, examples and fixtures. (2) Add `nativeWebTools` to `IProviderDefinition`; Anthropic profile maps `options.nativeWebTools.webSearch`; CLI `productProviderDefinitions()` enables it by default for every declaring definition unless the profile sets it. (3) Add `robota mcp add` and the first-start prompt: write `mcpServers` into `settings.json`, approve via the `/mcp approve` store, run before MCP composition, gated on an interactive TTY and interactive modes only. (4) Fix `agent-mcp` narrowing to emit only `IParameterSchema` keywords. (5) Bump `@robota-sdk/workflows` to 0.0.2 and pin it. Config lives in `$HOME/.robota/settings.json` (`mcpServers`) and `mcp-approvals.json` (`[{serverId, source, status}]`). Verify with `pnpm build && pnpm typecheck && pnpm lint && pnpm deps:check && pnpm test`, then a PTY run of `scripts/dev/agent` in a disposable HOME.

Try it yourself

In this repo, remove the vendor-backed WebSearch tool and replace it with two channels. (1) Model-native search as a provider construction option: add `nativeWebTools` to the provider definition type, let a profile enable `options.nativeWebTools.webSearch`, and have the CLI's single product provider-definition set turn it on by default unless the profile sets it. Delete any session-level `configureNativeWebTools`. (2) MCP servers: on first interactive start, ask once to add Exa (https://mcp.exa.ai/mcp) or Parallel (https://mcp.parallel.ai/mcp) or skip; write the choice to `settings.json` `mcpServers` and approve it in the same store `/mcp approve` uses, before MCP definitions resolve. Add `mcp add <exa|parallel|name https-url>` that refuses without a TTY and writes nothing. Remove the WebSearch tool, its provider interface, the Brave adapter and the `retrievalAdapter`/`computerDriver` options with no compatibility path. Then fix MCP schema narrowing so narrowed nodes keep only universal `IParameterSchema` keywords, dropping uncheckable constraints with a report and annotations silently, and stop reporting a standard `$schema` dialect as unenforceable. Add failing-first tests for each surface and verify with a real keyless MCP connection.

Source

Tools in this stack