web.search
web.search is called out by name in PLAN.md §4 as the single most important skill in Novaterra: it
is how a small, cheap model performs far above its weight. Every agent gets it by default
(DEFAULT_AGENT_SKILLS), and Muse leans on it for anything current, factual, numeric, or niche.
Schema
Input = { query: string, // min 1 char maxResults?: number, // 1-20, default 8 recency?: 'day' | 'week' | 'month' | 'year',}
Output = { results: Array<{ title: string, url: string, snippet: string, publishedAt?: string }>, provider: string, // 'tavily' | 'brave' | 'openrouter-online' | 'duckduckgo' | 'none' query: string, notes: string[], // backends tried and why they failed}The fallback chain
Backends are tried in this exact order, each one skipped if unavailable rather than erroring:
- Tavily — if
TAVILY_API_KEYis set. - Brave Search — if
BRAVE_API_KEYis set. - OpenRouter
:online— if an OpenRouter key is configured; asks acheap-tier model withonline: trueto search and return results, merging its own JSON array with the model’s URL citation annotations (annotations are authoritative for URLs; JSON items usually carry better snippets). - DuckDuckGo HTML — no key required at all; scrapes
html.duckduckgo.com, falling back tolite.duckduckgo.comif the HTML endpoint returns nothing (or a bot-challenge page).
A failing backend never throws out of the skill — its failure reason is appended to notes and the
next backend is tried. provider: 'none' with populated notes only happens if every single
backend failed. Results are deduplicated by normalised URL (query string and trailing slash
stripped) before being capped at maxResults.
Example
curl -s -X POST http://localhost:4000/api/studio/skills/invoke \ -H 'content-type: application/json' -b cookies.txt \ -d '{"name":"web.search","input":{"query":"OpenRouter pricing gemini 2.5 flash","maxResults":3}}'{ "ok": true, "output": { "query": "OpenRouter pricing gemini 2.5 flash", "provider": "duckduckgo", "notes": [], "results": [ { "title": "Gemini 2.5 Flash - OpenRouter", "url": "https://openrouter.ai/google/gemini-2.5-flash", "snippet": "Google's Gemini 2.5 Flash is a workhorse model..." } ] }, "durationMs": 612}See Environment variables for the TAVILY_API_KEY /
BRAVE_API_KEY settings, and web.fetch for reading a result page
in full, or web.research for a synthesised, cited answer in
one call.