Assay is one store. How you fill it depends on what you are doing.

Your own work with AI

You already talk to a coding harness. Assay reads the session logs that harness already wrote. Mode: corpus (the assay init default). Fill the store: assay capture … and assay sweep on. Labels: core. assay labelling on. Place sittings on the objective tree. Set type (kind of work). Read: Dashboard, search, share a sitting when someone outside needs the whole conversation. This path answers: what did I spend, on what, for which product, and what did we actually say.

Observability in an agent loop

You ship a product that calls models. Assay records each unit of work as it happens. It is still not in the request path: you call record after the model returns, or you export traces to the ingest door. Mode: observability. Fill the store: embed the library, or point OpenTelemetry at assay serve. Labels: optional. Sweep without labelling is enough. A cheap local judge is allowed. Do not treat that pass as corpus quality. Read: assay turns --json is the debug surface. The dashboard still works. Embedding <assay-dashboard> puts the same panels inside your own app, behind your login. This path answers: what did this loop spend, per user, per session, per task — and what did the loop say. See Agent loop and Debug console.
CorpusObservability
Who the work is forYou, buildingYour users, running your agent
CaptureFile sweep of harness logsrecord / recordTurn or OTLP
LabellingTurn it onOptional
Judge over full textSovereignty gateSame gate
Typical next readDashboard, objectives, shareassay turns, spend, waste
Init writes mode: "corpus" and both switches off. You choose.

What Assay never is

It does not wrap the model. It does not retry your calls. It does not hold API keys for providers you did not name. One verb, assay pricing watch, fetches public rate cards. That is the only network call in the CLI, and it does not open the store.