The guide shows what it says, with five tools made from the site's manifest

The assistant becomes the site's guide: it may open a page, point at something, run an experiment, start a tour or offer a next step, each call held to the site's manifest in code.

Status
Accepted 25 October 2026 · amends ADR 0019
The record
0021-the-guide-shows-what-it-says.md

Context

ADR 0019's assistant answers in words. A recruiter on the site also asks where things are and what an experiment shows, and the answer is often better shown than told: the experiment open, its leak running, a ring around the old generation. The site now describes itself in a manifest built with it, from the content the pages render: its pages, the parts worth pointing at, the experiments and their presets, the tours. The browser can carry out a command on it and say what it could not do. A model that may call tools can show; it can also be talked into showing what does not exist, into running on the server what nobody asked to see run, into acting where it should only offer, and every call of a loop costs. The lessons of ADRs 0017 to 0019 hold: narrow what the model may do, check in code what it does, bound what it can spend.

Decision

  • Five tools, made from the manifest. show_page, point_at, run_experiment, start_tour and offer each take one id, from an enum the server writes from the manifest: a page or a section of the home page, a part to point at, an experiment or an experiment with a preset, a tour, or one of four offers (the CV, an email, an introduction, the fit check). They are sent strict (strict: true, every object closed to other properties) and in a fixed order, the same bytes for every visitor. Their input is a word or two, so it streams buffered, and the server checks it against the schema all the same: strict mode holds the model to it, and this is the part the site does not take on trust.
  • Every call through a chain of checks. A call passes, in order: a tool that exists, with input in its schema; under the caps; sensible here: not the page the visitor is on already, on the server only when the visitor asked for a run and only where an experiment has a live run, a preset that runs on the server only as such a run. A call that passes becomes an action event for the browser, in the manifest's words (its label and its path, never the model's), and its result goes back to the model at once, from the manifest: "Opened Lab for the visitor." One that does not goes back as an error the model can correct. An offer is a button: nothing is sent or done until the visitor presses it, and the model is told so.
  • A turn, bounded. A question takes three model calls and four actions at most. The last call goes with tool_choice: none, so that it may only speak: every model takes it, and it keeps the cached tools and instructions, though the conversation's part of the cache is written again for that call. One gate runs across the calls and lets its pending sentence through before each action, so that the visitor reads the words and sees the actions in the order the model wrote them.
  • The gate holds back the first person. The record is in the owner's own words ("I review code and mentor mid-level engineers"), and a model may repeat them as if it were him. A sentence in the first person singular is held back, a connective too ("I did."), and the instructions say never to write I, me or my; the names of the site's parts and of the record's sections may still be quoted ("How I work"). The visitor is told why, as for the gate's other reasons.
  • The conversation only grows. The server keeps a conversation as the model was sent it: the questions, the model's turns exactly as they came, the tools' results. What is on the visitor's screen (the page, the home page's section, the experiment, whether it runs, its preset), which actions the browser could not carry out, and what the gate held back go to the model as a note after the next question, in the server's words, rebuilt from validated ids alone: an id the manifest does not have is dropped, and nothing a visitor typed goes in. The note is a system message where the model takes one in the middle of a conversation (Sonnet 5.5), and a <system-reminder> block in the question's message where it does not (Haiku 5.5 refuses such a request). An answer that fails on the way is not remembered. ADR 0019's last four turns give way to the whole conversation, which the cache makes cheap.
  • Cached. The tools, then the instructions, end in one explicit cache breakpoint, the same bytes for every visitor: the rules, the record with what the experiments' pages say, and the site's map, some 19,000 tokens by their 76,000 characters. The conversation's tail is cached automatically, so a follow-up reads nearly all of its prompt from the cache.
  • Claude Haiku 5.5, at low effort and without thinking, for the soonest first word. Sonnet 5.5 is one setting away (app.assistant.model), and a bake-off on the evals and on live questions chooses between them.
  • The assistant's endpoints and guards stay. A question's body gains screen and failed, its stream gains action, and done gains the number of actions, the cache tokens and the time to the first word; the public reference documents them. The switch, the day's budget, the bulkhead, the rate limits and the proof of work stay, and every call of a turn passes the budget and the bulkhead, each taking a place and giving it back. A conversation takes twelve questions instead of eight, and its proof of work asks 250,000 tries at most instead of a million: the browser solves it in the background as the guide opens, some 0.8 s for the mean 125,000 tries on a computer.
  • The adapter stays the site's own. Anthropic's Java SDK would type the tool blocks and parse the stream. It would also bring its own HTTP client and Jackson 2 beside the site's Jackson 3 into an image whose cold start is measured, and request shapes newer than its types would go in untyped all the same. The port already isolates the provider, and its adapter already reads the stream; the tool blocks added a few hundred lines to it. Considered, and declined (the research note).

Consequences

  • The guide can do only what the manifest names, and the manifest is built with the site: a page added is a page it can show, and a part the manifest does not name it cannot point at, however it is asked. A model talked into an address, a script or a tool of its own gets an error back, and the browser gets nothing.
  • The server never sees an action happen. The browser says with the next question what did not happen, and the model is told to claim nothing beyond a tool's result ("Opened Lab for the visitor", not "now you can see the leak").
  • The first-person rule costs a sentence now and then: a quote of the owner's words ("I measure before I guess") is held back, and the model is told so after the next question. The owner's words never come out of a machine as his.
  • A live run is the experiment's own public endpoint with its own limits (ADR 0006); the guide asks the browser to start it, and only when the visitor asked.
  • At Haiku 5.5's prices ($0.10 a million tokens in, $0.50 out, a cache read a tenth of the price in), a call that reads the instructions from the cache costs some $0.0002 for them, and one that writes them some $0.0024: a question of two calls about a tenth of a cent, a conversation of twelve about a cent, against ADR 0019's one to two cents a question at Sonnet's prices. These are estimates until they are measured on the real API, before the guide is turned on.
  • A question carries what is on the visitor's screen, by the manifest's ids, to Anthropic with it (ADR 0007), and the privacy page says so; nothing typed into a page goes with it.