Web search

Agents can issue /search <query> mid-turn to discover sources before fetching them — the missing piece that turned previous research turns into "guess a DOI from training memory and hope it resolves." Configured per-deployment via two ApiServerOptions fields:

FieldDefaultDescription
search_providerbraveSearch backend. Only brave is implemented in v1; tavily and exa slots reserved.
search_api_key""Provider API key. Empty ⇒ /search returns ERR with a clear "configure ARBITER_SEARCH_API_KEY" message.

arbiter and arbiter --api resolve the key in this order: ARBITER_SEARCH_API_KEY (preferred — provider-agnostic name), BRAVE_SEARCH_API_KEY (convenience for Brave-only deployments), then ~/.arbiter/search_api_key (written by arbiter --setup-tools). The provider can be set via ARBITER_SEARCH_PROVIDER. Without a key the slash command degrades cleanly: agents see ERR: web search unavailable with setup instructions and adapt by dropping the /search step.

In the interactive TUI, operator-typed /search mirrors /fetch: it bypasses the focused agent's capability list, calls Brave, and injects the result block into the conversation so the agent can synthesize.

Slash commands

CommandEffect
/search <query>Top 10 results for the query.
/search <query> top=NTop N results (clamped to 1..20). The top=N token is stripped from the query.

Capped at 4 searches per turn (vs. /fetch's 3), since result bodies are small and agents typically need a couple of search→fetch round trips per topic.

Result format

Numbered lines, one per hit, with title, snippet, and URL:

[/search planet nine 2024 top=5]
1. Title of the first result — Snippet text from the search engine, lightly trimmed.
   https://example.com/article-1
2. Second result title — More snippet text.
   https://example.com/article-2
...
[END SEARCH]

The dispatcher applies a 16 KB body cap (matching /fetch). Brave's <strong>...</strong> highlighting is stripped before rendering.

Provider notes

Bravehttps://api.search.brave.com/res/v1/web/search. The free tier gives 2,000 queries/month; production deployments should set a paid plan and a per-tenant rate limit at the proxy layer. Errors propagate verbatim:

SurfaceCause
ERR: web search unavailableNo search invoker wired (no key configured / process not restarted after --setup-tools).
ERR: Brave returned HTTP 401/403Bad key or plan / IP restriction.
ERR: Brave returned HTTP 422 [SUBSCRIPTION_TOKEN_INVALID]Invalid or truncated subscription token.
ERR: Brave rate-limited (429)Quota exhaustion.
ERR: empty query/search with no terms.
ERR: capability not granted … bundle 'web'Mid-turn agent /search while the agent's capabilities omit /search, /fetch, and /browse.

Workflow for agents

The master constitution (and every research-flavoured starter agent) instructs agents to search → fetch → browse, in that order of escalation:

/search planet nine orbital clustering 2024
                                                       # next turn returns ranked URLs
/fetch https://arxiv.org/abs/2403.05451                # cheap libcurl read — preferred
/browse https://www.nature.com/articles/...            # JS / paywall — playwright

Guessing URLs from prior knowledge produces fabricated DOIs and dead links — /search discovers them, /fetch reads them when the page is static, and /browse falls back to a real browser when /fetch hits Cloudflare's "Just a moment", a login wall, or an SPA-only page.

See also