Agent Architecture
How the AI agents are built server-side - the roster, the grounding contract, tool use, and the human-commit gates.
How the AI agents are built server-side: the roster, the grounding contract, tool use, and the human-commit gates. Product docs
05(chat),13(autonomy),16(chat-first) describe behavior; this is the implementation.
The agents (all server-side, never in the browser)
| Agent | Job | Writes? |
|---|---|---|
| Analyst | answer grounded questions over the canonical model; draft cases/reports | drafts only; human commits |
| Ontology | source onboarding: profile feed → propose field mapping → dry-run | stages mapping (Q9) |
| Adjudicator | wargame: draft consequences of a cell's action | drafts; faculty approves |
| After-Action | replay a session/case → draft the signed report | drafts; human signs (Q8) |
| Watch | standing monitor: detect → draft a Proposal | internal-reversible only (Q10) |
All share one grounding contract and one tool layer; only their system prompt, tools allowed, and output schema differ.
The grounding contract (enforced, not requested)
A claim about the world must cite ≥1 observation by id ([OBS-####]) or it does not ship. Enforcement is two-sided:
- Prompt: the system prompt requires citations and forbids ungrounded assertions.
- Validator: a server-side checker parses every claim's citations, resolves each id against Postgres for the tenant, and rejects + regenerates any draft with a dangling or cross-tenant citation. The model cannot talk past the validator because the validator reads the citation graph, not the prose. (See
ai/31for the validator.)
Tool layer (Claude tool-use)
Agents don't get raw DB access; they get a typed tool surface that already enforces tenant scope, RLS, and classification:
tools = [
query_observations({ entity?, property?, since?, until?, bbox? }) -> Observation[] // RLS-scoped
get_entity({ id }) -> Entity
search_corpus({ query, entity?, k }) -> Chunk[] // RAG retrieval (ai/31)
list_events({ entity?, case?, since? }) -> Event[]
base_rate({ metric, entity_type, context }) -> Distribution // for "unusual vs what"
// write tools are PROPOSE-only:
propose_case_update({ case, patch }) -> ProposalId
propose_report_section({ report, section }) -> ProposalId
]Every tool call runs as the requesting user's tenant + role context, so an agent can only ever see/act on what that user could. Write tools propose; they never commit. This is the Q8/Q10 spine in code.
Confidence & base rates
The analyst is told to express "unusual" as a number against a base rate, not an adjective — the base_rate tool returns the historical distribution so output reads "loiter 4h12m vs 90th-pctile 38min [OBS-…]". Where the sample is too small for a defensible interval, the agent emits the point estimate + sample size + an explicit "interval withheld" note rather than fake precision.
Run records
Every agent invocation writes an agent_runs doc (Mongo): the prompt, retrieved context (chunk + obs ids), tool calls, raw model output, parsed citations, validator result, and final output. This is the audit + debugging surface and feeds Trust Evals (product §13).
Orchestration
- Chat/analyst calls run inline (request/response, streamed).
- Watches and After-Action run async (Cloud Tasks / Pub-Sub jobs) and stage Proposals.
- A single
packages/agentsmodule defines tools + validators so every entry point shares identical enforcement.
Decided
- Model routing: a Sonnet-class model for the analyst chat + high-volume agents; an Opus-class model for the Adjudicator + After-Action (quality-critical, lower-volume). Resolve current GA model strings at build time (don’t hardcode).
- Output schemas + citation grammar are pinned in
80-contracts-citation-and-schemas.md— the validator is built against them.
Gaps to close
- Finalize each proposal
patchshape per type (the rest of the schemas live in80). - Decide model routing (which Claude model per agent; cost vs. capability) and token budgets.
- Specify the base-rate service data sources and minimum-sample thresholds.
- Wire
agent_runsinto Trust Evals scoring (defensibility scorecard).
Data-Source Integration & the Responsibility Boundary
insigz integrates any source through the canonical contract, but the customer owns the data rights, cost, credentials, and lawful authority.
RAG & Context Assembly (how context gets into the AI)
The pipeline that turns a question into a grounded, citation-checked answer - the RAG file system and the context window builder.