About the console
The console is where a scientist talks to the agents inside a program. It is designed to feel like working with a careful colleague who has read the papers, knows which SOP version is in force this week, can see the notebook entry you just finished, and never touches the record without asking. This page explains the choices behind that feeling; the console reference lists the fields and the tutorial walks through one exchange.
The positioning it serves
The pilot is positioned once and everywhere as “non-GxP decision support with a light validation package”. The ELN stays the scientific record, the QMS stays the SOP record, Trovensa is the record of what agents proposed and what people decided. Nothing in the console claims regulatory compliance; the controls (plan gates, approval with the write’s own permission, citations, audit envelope, signatures) are described so a buyer or a reviewer can inspect them. This is the right shape for a mid-size biotech between discovery and IND: one ELN, one SOP library, no validation department to spare, and adoption only if the agent saves hours on evidence work and SOP checking while leaving an inspectable trail.
Why a program section, not a fifth product
Products are record types: Evidence, Plans, Review and Progress each own tables, permissions and a lifecycle.
The console owns none of those; it is a way of working with them. Making it a section at
/p/<slug>/console keeps every accepted proposal an ordinary record with origin = agent in the product that
owns it, keeps the permission grammar closed (no “console” product segment; nine new program-scope keys
instead), and lets the rail show it to anyone who can read their own threads.
Why three regions
Conversation, canvas and run rail separate three things a reader wants at different moments: what was said,
what is being produced, and what the agent actually did. The conversation carries plan and approval cards
because a decision belongs where the question was asked. The canvas renders artifacts from a fixed vocabulary
(plan, finding_set, deviation_table, sop_diff, …) through UI-owned components rather than free-form
generated interfaces, so every artifact is predictable, versioned and promotable. The run rail shows tool calls
with their policy decision, permission_exercised and span id, the sources read, the budget used, the SOP
binding and the model configuration record, because trust comes from being able to look.
Why plan-first, propose-only
Every run starts with a plan artifact that names actions, tools, sources, expected writes and budget, and the
approved plan becomes the control flow: a tool outside it is refused (plan_violation). Every write is a
tool_calls proposal that a person approves with one key, edits, or declines with a reason, and approving
needs the write’s own permission, recorded as permission_exercised. Agents hold no approve, sign or notify
tools at all; those are structurally absent rather than policy-denied. The result is that the record never
changes without a named person, the person’s permission is the one the record type already defines, and the
reason for a decline becomes evaluation data.
Three run modes (“Run and approve each write”, “Run with automatic reads and gated writes”, “Keep planning”) let the person choose how much ceremony reads deserve; writes are always gated.
Why private threads with an oversight read
A chat holds thinking aloud. If every thread were readable by every program member, scientists would not use
it; if none were, quality reviewers would lose the oversight the regulatory frame expects. Threads are
therefore private by default (program.threads.read_own), quality reviewers and program leads can read every
thread (program.threads.read), and the composer says so with a fixed sentence. Visibility changes only by
the owner’s explicit Share with program action, with a confirmation naming what becomes visible;
program.threads.manage covers archive and export with a reason, never sharing. The same rule governs the run
rail’s routes, so a private thread cannot be read through its run’s events. A record created from a private
thread still shows its run snapshot, citations and decision on its own page, with the link “From a private
thread”. ADR 0020 records the alternatives.
Why citations are counted, not judged
Every factual sentence carries a marker bound to a chunk, and the header counts claim-shaped sentences without one (“All 9 claims carry a citation”). This is called citation coverage, not grounding, because it verifies markers and not that the passage supports the claim; semantic grounding is a judged check in the evaluation suite. A soft count in R1 avoids retracting prose on a heuristic that has not been calibrated.
Why streaming and gates are shaped this way
Turns stream through a durable event log: the worker consumes a streamed turn from the runtime, writes
agent_events, and the API tails the table and serves server-sent events per thread with a keepalive and
Last-Event-ID resume. The database is the source of truth for every turn, so a gate can wait minutes or
hours, a release can roll the runtime, and the resumed decision does not depend on runtime state. A card that
waits more than 15 minutes becomes a background run card and stays actionable; an expired gate ends the run
with gate_expired and Resume opens a new decision.
What the design leaves out on purpose
- No writes into the ELN or the QMS: drafts stay in Trovensa; scientists carry them over with the provenance footer.
- No model names anywhere: the UI shows “Model configuration MC-n (recorded
<date>)”, verified at run start. - No memory beyond the thread and the records in R1 and R2; the panel says so with a
designedchip. Memory, when it arrives, is operational continuity, never a record of decision. - No numbers in copy (latency, cost, quality) until they are measured and registered in
CLAIMS-REGISTER.md. - No compliance claim: controls are described.