Web search

Web search answers questions outside Atamaia's stores — current docs, error messages, public pages. It is not memory search, not the code graph, and not facts.

One implementation serves both the platform route and agent/MCP tools on purpose. Two consumers of one idea drift apart; a dead primary that only one path noticed is how search stayed "fine" for weeks while quality collapsed.

All endpoints require authentication. Responses are wrapped in ApiEnvelope<T> on REST. Canonical API host: https://api.atamaia.ai.


What it is (and is not)

Is: a meta-search call that returns titles, URLs, snippets, and which provider answered.

Is not:

  • Grounding that is automatically written to memory (caller decides what to keep).
  • A guarantee of engine ranking quality — that depends on upstream engines behind SearXNG.
  • Google Programmable Search as the product primary (that era ended; see below).

Why SearXNG replaced what came before

Previous order: Google Programmable Search Engine, falling back to DuckDuckGo HTML scraping.

What broke (service remarks, 2026-08-12):

  1. Google discontinued PSE. Prod's configured key returned HTTP 400 "API key not valid."
  2. Failure fell through to the scraper silently. Agents still got results; nothing said the primary was dead.
  3. Worse: prod carried External__Google__ApiKey=CHANGE_ME. IsNullOrEmpty treated it as set, so the tool sent the literal placeholder to Google. That looked like an expired key rather than a key that had never been configured — scraper from day one, invisible.

SearXNG is now first:

  • Self-hosted per box (deploy/searxng), bound to loopback
  • No API key, no cloud quota
  • Queries many engines at once — one upstream blocking degrades quality instead of breaking search
  • Default URL: http://127.0.0.1:8888 (External:SearXNG:Url)

Fallbacks remain but are loud: Warning logs name the provider; the response provider field is part of the contract so callers can see degradation without reading logs.


Provider chain

Order provider value Notes
1 searxng Healthy path
2 google-pse Only if real key + cx; placeholders skipped
3 duckduckgo-scrape HTML regex parse — brittle; last resort
none Every provider failed; empty results

Caller rule: if provider is anything other than searxng, treat results as degraded — usable under caution, not equivalent to the primary.

Live probe (2026-08-13): query Atamaia AI platformprovider: "searxng", three hits, engines listing e.g. google cse, duckduckgo (upstream engines inside SearXNG, not the platform fallback names).


How a caller uses it

REST

GET /api/system/web-search?query={q}&maxResults={n}

Aliases: q for query. maxResults optional (service default 8).

Response (WebSearchResponse):

Field Type Meaning
query string Echo of the request
provider string searxng | google-pse | duckduckgo-scrape | none
results array Hits

Hit (WebSearchHit):

Field Meaning
title Result title
url Link
snippet Short text
engines Upstream engines (SearXNG only; empty on fallbacks)

MCP / tools

MCP tool web_search (and the agent WebSearchTool) call the same IWebSearchService. Same provider field, same degradation contract.

Listed as a hot tool in MCP packaging — an assistant that cannot look anything up is hobbled for current facts.

Example (shape)

{
  "query": "Atamaia AI platform",
  "provider": "searxng",
  "results": [
    {
      "title": "Atamaia — The platform for AI identity, memory, and context",
      "url": "https://atamaia.ai/",
      "snippet": "Give your AI a mind of its own…",
      "engines": ["google cse", "duckduckgo"]
    }
  ]
}

Ops notes that bite

  1. JSON is off by default in SearXNG. Without formats: [html, json] in settings.yml, the web UI works and the API returns 403. Browser check "is it up?" passes while Atamaia gets nothing. See deploy/searxng/settings.yml.
  2. Loopback only — the platform reaches SearXNG on the same host; remote callers use Atamaia's API, not SearXNG directly.
  3. Placeholders are not credentials. Values containing CHANGE, PLACEHOLDER, YOUR_, or equal to TODO/xxx skip Google PSE with a Warning. Absent is better than fake-configured.
  4. Timeouts are 15s per provider attempt in the service.

Relationship to other search

Need Use
Identity/work memories memory_search — see docs-memory-surfaces.md
Code / internal docs symbols graph_search — see docs-code-graph.md
Project facts fact_search
Public web this/api/system/web-search

Do not file web snippets into work memory as Asserted without labelling provenance; prefer Reported/Inferred when recording.


Endpoint catalog

GET /api/system/web-search

Implementation: Atamaia.Services.Search.WebSearchService.
Contract: Atamaia.Core.Services.IWebSearchService.
Deploy: deploy/searxng/.


Rough edges

  1. DuckDuckGo fallback depends on HTML class names (result__a, result__snippet) — markup change → empty parse + Warning.
  2. Google PSE retained only as a historical safety net; discontinued upstream.
  3. No caching layer described in the service — repeated identical queries hit SearXNG again.
  4. Agent tool may expose extra args (e.g. focus) that the REST route does not; REST is the thin shared core.