ADR 0016 — Host web-search tool: optional real binding, offline stub default¶
Status: Accepted (stub + fake/tavily + example; runtime.yaml tools block deferred). Envelope generalized by ADR 0020.
Context¶
tool: states and the host registry ((dict) → str, entry points mklang.tools)
are language-complete (SPEC §4.9). The reference builtin search must stay
honest offline while allowing production hosts to bind a real backend without
provider-native tool-calling or browser automation.
Decision¶
- Protocol unchanged. Web search is a host tool named
search. Input:{"query": "…", "max_results"?: N, "days"?: N, "topic"?: "news"|"general"}. Observation: a JSON string with ADR 0020 envelope fieldstool,stub,errorplusquery,results:[{title,url,snippet,published_date?}](and optionalmessage). Recency fields are optional; backends that ignore them stay valid. Unbound / fake →stub: true; live Tavily →stub: false. - Default remains the offline stub — no search API key on core install.
- Real binding is opt-in via
mklang.search.configure_searchor envMKLANG_SEARCH_BACKEND=fake|tavily(+TAVILY_API_KEYfor Tavily). Convenience: ifTAVILY_API_KEYis set andMKLANG_SEARCH_BACKENDis unset, Tavily is selected automatically (the key is the host opt-in).MKLANG_SEARCH_BACKEND=stubforces offline. Entry-point plugins may still overridesearchentirely. - No language change. Example:
examples/research_web.mk(+ scenario test). Time-sensitive machines declarecontext.today: ""; hosts fill empty declaredtodaywith the ISO date (host convention, not a SPEC face). Wall-clock machines may also declarecontext.now: ""for a local ISO datetime fill (same inject path; not a search concern). - Threat model. Search observations are untrusted context (SPEC §11).
Checklist¶
| Item | Status |
|---|---|
| Structured stub default | done |
| Fake + Tavily backends | done |
research_web.mk + scenario test |
done |
| SPEC / patterns note | done |
Optional days / topic / published_date |
done |
Host context.today convention + research patterns |
done |
Host context.now (wall-clock local ISO datetime) |
done (same inject path; not search-specific) |
runtime.yaml tools.search block |
deferred |
| Console-specific consent copy for search | deferred (generic tool consent covers it) |
stdlib std_research |
deferred |
Consequences¶
- Authors write portable
tool: searchmachines; demos work offline. - Injection surface grows with web text — documented, not denied.
- Provider-native web tools stay out of core (ADR 0003).