Agent Audit Projection Architecture
Companion to: QC + Sales & Market + Recall & Proof arch docs (this is the 4th in the projection-architecture family).
Source catalog: docs/projections/PROJECTION_CATALOG_2026-05-15.md §6.5.
0. TL;DR
Every agent session becomes a citable, replayable, queryable doc. Single projector with big leverage: regulatory review, federal audit, customer dispute resolution, gradeboard A/B all read the same agent_harness_session.<session_id> projection.
agent runtime events → ripple
─────────────────────────────────────────────────────────────────
agent.session.started → agent_session_projection row open
agent.tool_called → append to session.tool_log[]
agent.tool_returned → append to session.tool_log[] (paired)
agent.message_emitted → append to session.message_log[]
agent.action_proposed → append to session.actions[]
agent.action_committed → append to session.actions[]
provenance.walked → append to session.provenance_walks[]
doc.section_generated → append to session.doc_drafts[]
agent.session.completed → close session_projection
+ render agent_harness_session.<id> vault MD
+ emit content_hash for replay verification
Output is queryable by: actor, tenant, time window, tools-invoked, entities-touched, model+version, prompt_version, latency, cost, outcome (committed vs proposed-not-committed).
0.5 Central-overlay reads contract (3-rung taproot — see AOL §13.6)
This family is unique among the four: the projector itself is rung-3 tenant-private (agent sessions are tenant data), but the projector MUST CAPTURE which Central MDs the agent read during the session. The agent’s agent.tool_called for get_entity_profile / search_entity_profiles events implicitly read from rung-3 fused output; the underlying assembly reads from both tenant knowledge and _taproot_mirror/. The session projection captures BOTH layers’ content_hashes at the moment-of-read.
| Field on projection | Source | Why |
|---|---|---|
session_central_reads[] | every agent.tool_called with tool ∈ {get_entity_profile, search_entity_profiles, walk_provenance, get_doc_graph} | Captures which Central MDs the agent referenced |
session_central_md_pins[] | sha-256 of each _taproot_mirror/ MD content at the moment of read | Replay reproducibility: at T+6mo, what did the Central MD look like when the agent read it? |
session_tenant_overlay_pins[] | sha-256 of each tenant overlay MD at the moment of read | Same, for tenant-side fusion inputs |
session_assembly_decision_log[] | log of which planes (1/2/3) the assembler chose per tier | Per AOL §13.2 three-tier retrieval — captures the “which tier was used” record the catalog spec mandates |
Why this matters: federal audit asks “show me what the agent saw when it made decision X.” Without Central-pin capture, T+6mo Central MD changes (e.g., commodity profile updated with new defect class) would silently mutate the “what the agent saw” picture. Pinning prevents that.
Read contract: the projection READS from agent.* events only — it does NOT directly read _taproot_mirror/. The Central MD content_hashes are captured at write-time by the agent runtime (when the agent calls get_entity_profile, the tool emits the content_hash alongside the response) and persisted on the agent.tool_returned event payload.
Runtime instrumentation requirement: get_entity_profile + search_entity_profiles + walk_provenance + get_doc_graph tools MUST emit central_md_content_hashes[] + tenant_overlay_content_hashes[] on their agent.tool_returned event. This is a small (~30 LOC) extension to those 4 tools. Add to Sequence AA1 as AA1-D.
Write contract: projector writes to tenant paths (docs/agent-audit/...) only.
1. Vault MD projector (rung 3)
1.1 agent_harness_session.<session_id>
- doc_kind:
event_digest - audience: FIN operator + employee (the actor who ran the session) + customer / vendor (filtered, when their portal session) + federal (when subpoenaed)
- cadence: event-driven on
agent.session.completed+ on-demand re-render (post-session enrichment) - path:
nathel-intranet:docs/agent-audit/sessions/<YYYY-MM>/<session_id>.md - sources:
agent.session.started(open envelope: actor_id, tenant_id, role, model, version, prompt_version, started_at)agent.tool_called(each: tool_name, params, called_at, request_id)agent.tool_returned(each: request_id paired with call, returned_at, result_shape, latency_ms, success/error)agent.message_emitted(each: stream_position, role, content, tokens_in/out)agent.action_proposed(each: action_kind, params, proposed_at, status_at_close)agent.action_committed(each: action_kind, params, committed_at, resulting_event_id)provenance.walked(each: from_entity, to_entity, hops, terminator)doc.section_generated(each: section_id, content_hash, accepted_by_actor)- Cost / latency rollup (sum of tool calls + LLM tokens × price_table_at_session_start)
- Replay manifest (frozen event-id set + renderer_version + content_hash)
- output shape:
- Section 1: session envelope (actor / tenant / role / model+version / prompt_version / started_at / completed_at / duration / outcome)
- Section 2: tool-call log (table: name / params / latency / success — agent’s tool-use timeline)
- Section 3: message log (full transcript, role-alternating)
- Section 4: actions proposed vs committed (which ones the actor confirmed, which were dropped)
- Section 5: citations emitted (every event_id / knowledge row / doc the agent cited in its messages)
- Section 6: provenance walks (each walk’s chain + terminator + duration)
- Section 7: drafts proposed (each doc.section_generated link, with acceptance status)
- Section 8: latency + cost rollup (charts: tokens_in/out per turn, tool latency per call, total session cost)
- Section 9: replay manifest (frozen_input_event_id_range + renderer_version + content_hash)
2. JSONB projections
2.1 agent_session_projection (NEW)
- migration:
075_agent_session_projection.sql - schema:
tenant_id × session_id → { envelope, tool_log[], message_log[], actions[], citations[], provenance_walks[], doc_drafts[], cost_rollup, latency_summary, closed_at, content_hash } - source events: all
agent.*+provenance.walked+doc.section_generatedevents for this session - replay command:
pnpm cli replay-projection --projection=agent_session_projection --tenant=<tenant_id> - RLS: required
- fed-by:
event-handlers/projection-agent-session.ts(NEW) - consumed-by:
agent_harness_session.<session_id>renderer + gradeboard A/B + dispute resolution tooling
2.2 agent_enrichment_metrics_projection (NEW)
- migration:
076_agent_enrichment_metrics.sql - schema:
tenant_id × week → { proposals_count, acceptance_count, acceptance_rate, doc_enrichment_count_per_agent[], reasoning_quality_lift_a_vs_b } - source events:
doc.edit_proposed,doc.edit_accepted,doc.edit_rejected, gradeboard A/B measurement events - replay command:
pnpm cli replay-projection --projection=agent_enrichment_metrics_projection --tenant=<tenant_id> - RLS: required
- fed-by:
event-handlers/projection-agent-enrichment-metrics.ts(NEW) - consumed-by:
agent_enrichment_metricsvault MD (catalog §6.7) + federal_readiness_tracker
2.3 agent_eval_drift_projection (NEW)
- migration:
077_agent_eval_drift_projection.sql - schema:
tenant_id × scenario_id × week → { score_ema, confidence_trend, drift_class, stale_flip_count } - source events:
system.scenario_eval_result(existing — P0-07 consumer fills this) - replay command:
pnpm cli replay-projection --projection=agent_eval_drift_projection --tenant=<tenant_id> - fed-by: existing P0-07 consumer extended (
projection-eval-feedback.ts) → write drift class into new projection table - consumed-by: internal LLM eval dashboards +
agent_enrichment_metricsvault MD
3. Why this matters (use cases)
| Use case | Reads this projection |
|---|---|
| Regulatory review (FDA, USDA) — “show me every agent decision affecting this lot” | agent_session_projection filtered by entities.lot_id |
| Federal audit (FedRAMP, SBIR/STTR) — “show me agent behavior in this date range” | agent_session_projection filtered by started_at BETWEEN |
| Customer dispute resolution — “did the agent recommend this rejection?” | agent_session_projection filtered by actions.action_kind = sales.rejection_proposed |
| Gradeboard A/B — “did prompt_version v3.4 improve customer outreach acceptance rate?” | agent_enrichment_metrics_projection joined by prompt_version |
| Eval calibration — “is the agent’s confidence on blackberry holding steady or drifting?” | agent_eval_drift_projection filtered by scenario_id LIKE 'commodity:blackberry%' |
| Cost / latency observability — “which tools are slow?” | agent_session_projection.tool_log[] aggregated by tool_name |
| Citation auditing — “what fraction of agent claims cite source events?” | agent_session_projection.citations[] counted vs message_log[] claim count |
4. Native comms integration
| Surface | Where Agent Audit projections land |
|---|---|
| FIN operator rail | Daily summary of yesterday’s agent sessions: counts, drift alerts, exception sessions |
| Compliance role rail | Sessions touching compliance.* or recall.* events automatically pinned for review |
| Customer portal | ”View what the agent did for you” — shows customer-filtered session summary |
| Slack | Weekly agent_enrichment_metrics digest to #agent-eval channel |
Quarterly: agent_audit_quarterly_summary to FIN operator + compliance | |
| Gradeboard dashboard | Live read from agent_eval_drift_projection |
5. Frontmatter contract
---
schema_version: 1
doc_id: agent_harness_session_<session_id>
doc_kind: event_digest
title: Agent Session <session_id> — <actor> @ <tenant>
slug: agent-harness-session-<session_id>
source_attribution:
- producer:agent_harness_session_renderer
- source_session_id:<session_id>
- source_events:<comma-separated event_ids in frozen input set>
- renderer_version:<semver>
- content_hash:<sha256>
lifecycle_status: active
created_at: <session_started_at>
updated_at: <session_completed_at>
maintained_by: agent_harness_session_renderer
visibility: company | restricted | customer_visible
data_plane: relationship_data
linked_entities:
- { type: actor, id: <actor_id> }
- { type: tenant, id: <tenant_id> }
- ... every entity the agent touched (commodity / vendor / customer / lot / po / etc.)
tags: [agent_audit, session, replay, ...]
determinism_required: true
re_render_hash_drift_alert: true
---6. Build sequence
Single-projector family — smallest of the four arch docs.
Sequence AA1 — 3 JSONB projections (~2 days)
- AA1-A
agent_session_projection(migration 075 + handler + dispatcher + test) - AA1-B
agent_enrichment_metrics_projection(migration 076 + handler + dispatcher + test) - AA1-C
agent_eval_drift_projection(migration 077 + extend existing P0-07 consumer)
Sequence AA2 — 1 vault MD renderer (~1-2 days, DETERMINISTIC)
- AA2-A
agent_harness_session.<session_id>renderer (event-driven onagent.session.completed+ content_hash machinery)
Sequence AA3 — Agent surface + tooling (~1 day)
- AA3-A
get_agent_session(session_id)MCP tool (FIN operator + audience-filtered) - AA3-B
query_agent_sessions(filters)MCP tool (cross-session search) - AA3-C
get_agent_enrichment_metrics(window)MCP tool - AA3-D Operator-rail integration
Total: ~4-5 days.
7. Coordination with other arch docs
| Other arch doc | Agent Audit dependency |
|---|---|
| QC arch | QC agent sessions (qc_inspector talking to agent) tracked here; replay supports inspection-decision audits |
| Sales & Market arch | Sales agent sessions tracked; gradeboard A/B for sales outreach prompts measured via agent_enrichment_metrics |
| Recall & Proof arch | Recall investigation agent sessions automatically pinned for federal review; investigator’s agent session itself becomes part of the recall evidence bundle |
8. Open questions
| ID | Question | Default |
|---|---|---|
AA-Q1 | Session boundary — single agent invocation, full user-conversation, or work-thread scope? | Full user-conversation (matches actor mental model); explicit agent.session.started + completed events bracket it |
AA-Q2 | Re-render trigger on post-session enrichment events (doc.edit_accepted after the session closes) | Yes — bump updated_at, recompute content_hash, emit agent_harness_session.re_rendered |
AA-Q3 | Should LLM tokens / cost be in the public-anonymized variant? | No — strip cost (commercial-sensitive); keep model + version |
AA-Q4 | Cross-session memory references (actor.memory updates) — link to session? | Yes — doc.section_generated for actor.memory writes carries the session_id |
AA-Q5 | Failed sessions (agent.session.error) — render anyway? | Yes — failures are most-audit-worthy |
AA-Q6 | Retention — same as recall (7 years) or longer? | 7 years per FSMA; recall-touching sessions retained indefinitely (same rule as recall evidence) |
9. Productization mapping
| Offering | Agent Audit projector that enables it |
|---|---|
| G-3 Outbreak Investigation Support | Investigator agent sessions auto-included in recall evidence bundle |
| G-5 Anti-Fraud Signals | Cross-tenant agent session patterns surface anomalous agent behavior |
| B-5 Custom Reports | Per-tenant agent ROI report: tasks completed × outcomes attributed × cost |
| Internal gradeboard / eval | agent_eval_drift_projection is the eval dashboard substrate |
| Tier 2 quarterly customer proof | proof_package cites agent sessions that demonstrably improved customer outcomes |
This arch ships the substrate for 5 of the 17 strategy doc offerings (overlap with Recall & Proof + Sales & Market).
10. Sign-off
This arch is the canonical reference for any future agent-session, eval, gradeboard, or replay-audit projection work. Future projectors in this family MUST cite this doc in their PR description. Cross-mirrored to fin-central-intranet:docs/architecture/AGENT_AUDIT_PROJECTION_ARCHITECTURE_2026-05-18.md.
— claude_orchestrator (Opus 4.7 1M-context, session 7612a827-b892-47e3-86cd-08835737208e)