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 projectionSourceWhy
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 readReplay 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 readSame, for tenant-side fusion inputs
session_assembly_decision_log[]log of which planes (1/2/3) the assembler chose per tierPer 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_generated events 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_metrics vault 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_metrics vault MD

3. Why this matters (use cases)

Use caseReads 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

SurfaceWhere Agent Audit projections land
FIN operator railDaily summary of yesterday’s agent sessions: counts, drift alerts, exception sessions
Compliance role railSessions touching compliance.* or recall.* events automatically pinned for review
Customer portal”View what the agent did for you” — shows customer-filtered session summary
SlackWeekly agent_enrichment_metrics digest to #agent-eval channel
EmailQuarterly: agent_audit_quarterly_summary to FIN operator + compliance
Gradeboard dashboardLive 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 on agent.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 docAgent Audit dependency
QC archQC agent sessions (qc_inspector talking to agent) tracked here; replay supports inspection-decision audits
Sales & Market archSales agent sessions tracked; gradeboard A/B for sales outreach prompts measured via agent_enrichment_metrics
Recall & Proof archRecall investigation agent sessions automatically pinned for federal review; investigator’s agent session itself becomes part of the recall evidence bundle

8. Open questions

IDQuestionDefault
AA-Q1Session 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-Q2Re-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-Q3Should LLM tokens / cost be in the public-anonymized variant?No — strip cost (commercial-sensitive); keep model + version
AA-Q4Cross-session memory references (actor.memory updates) — link to session?Yes — doc.section_generated for actor.memory writes carries the session_id
AA-Q5Failed sessions (agent.session.error) — render anyway?Yes — failures are most-audit-worthy
AA-Q6Retention — same as recall (7 years) or longer?7 years per FSMA; recall-touching sessions retained indefinitely (same rule as recall evidence)

9. Productization mapping

OfferingAgent Audit projector that enables it
G-3 Outbreak Investigation SupportInvestigator agent sessions auto-included in recall evidence bundle
G-5 Anti-Fraud SignalsCross-tenant agent session patterns surface anomalous agent behavior
B-5 Custom ReportsPer-tenant agent ROI report: tasks completed × outcomes attributed × cost
Internal gradeboard / evalagent_eval_drift_projection is the eval dashboard substrate
Tier 2 quarterly customer proofproof_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)