Forensic Session Viewer
Post-mortem inspection of completed agents-fleet sessions through a localhost-only browser UI. Replay tool calls, messages, state transitions, token accounting, and full event payloads — without re-running the session.
What it captures
When forensic telemetry is enabled — which is the default — agents-fleet writes a full-payload event ledger alongside each session. The ledger is an NDJSON file at ~/.fleet/sessions/<sessionId>.events.ndjson and includes:
- LLM prompts (verbatim)
- LLM completions (verbatim)
- Tool calls and results (with full arguments and full output)
- Permission / decision-dialog request and resolution payloads
- Coordinator ↔ worker inter-agent messages
- State transitions and lifecycle events
- Token usage snapshots (input, output, cache read/write)
Sensitive data warning. Capture is ON BY DEFAULT — opt out with
AGENTS_FLEET_SESSION_TELEMETRY=0. Capture applies ZERO redaction. Ledger files contain the complete, unredacted payloads of every captured event — including source code, prompts, completions, tool arguments, tool results, and any secret that flowed through the session. Any API key, bearer token, or credential passed as a tool argument is written to disk in plaintext. agents-fleet does not delete ledger files at session end; they are reaped at the next startup once they fall outside the retention window or budget (see Retention). Redaction is intentionally out of scope; the startup caution below is the mitigation.
Capture is on by default
Forensic capture is enabled by default. Every session records a ledger unless you explicitly opt out:
# Opt out — no ledger file and no ledger directory are created.
AGENTS_FLEET_SESSION_TELEMETRY=0 agents-fleet0 and false (trimmed, case-insensitive) disable capture. Every other value — unset, 1, true, or an unrecognized value — leaves capture on, so a typo never silently loses evidence.
The ledger file is created automatically and capped at 50 MB by default. Override the cap with:
AGENTS_FLEET_SESSION_TELEMETRY_MAX_MB=100 agents-fleetThe value must be a positive number (in megabytes). When the cap is reached, further events are silently dropped for that session.
Startup caution
The first time capture is initialized in a process, agents-fleet prints a one-time security caution to stderr naming the ledger path and the risks above, including the AGENTS_FLEET_SESSION_TELEMETRY=0 opt-out. It is emitted by emitForensicTelemetryCaution and latched in RuntimeForensicCapture.createFromEnvironment, so it fires once per process at startup — never per captured event. It does not fire at all when capture is opted out.
Starting the replay viewer
After one or more sessions have been captured, start the replay service:
agents-fleet --forensic-viewerThis starts (or reuses) a localhost HTTP service that:
- Binds to
127.0.0.1only (never exposed on the network). - Listens on an ephemeral port chosen at startup.
- Serves the forensic browser app and a bearer-token-authenticated JSON API.
- Writes a descriptor file at
~/.fleet/forensics/viewer-server.jsonadvertising the running instance (port, bearer token, PID).
Override the descriptor location with:
AGENTS_FLEET_FORENSIC_VIEWER_DESCRIPTOR=/path/to/descriptor.json agents-fleet --forensic-viewerThe service prints a launch URL to stdout. Open it in your browser to start exploring sessions.
Browser UI
The viewer provides:
- Session list with search across all completed sessions.
- Per-session timeline with text search, category/type dropdown filters, and actor-lane flow navigation.
- Event correlation and drill-down — transcript anchors, tool details, errors, and state snapshots.
- Full event payload display with syntax highlighting.
- Token accounting — input, output, cache read/write totals and tokens/second throughput.
- Availability notices — sessions captured with telemetry enabled show "Complete forensic ledger". Legacy, partial, or corrupt ledgers surface a graduated notice (partial / unavailable) with per-data-source status.
Completed sessions only. The viewer replays finished sessions; it does not stream events from a running session.
Known limitation: ?agentId= on the legacy replay path
The ledger API endpoint accepts an ?agentId= query parameter to filter events down to a single agent. This works only for ledgers written by RuntimeForensicCapture.
On the legacy replay path, ?agentId= always returns an empty result set. Legacy projection events are synthesized with actor: { type: 'system' } and carry no correlation data, so there is no per-agent attribution for the filter to match against.
This is an honest limitation of legacy projection fidelity, not a bug — the legacy source genuinely lacks the attribution the filter needs. Use the unfiltered timeline (or the text search / category filters) when inspecting a legacy session.
FleetConsole integration
The optional desktop companion is maintained separately in vriveras/agents-fleet-console. Its application, launcher, and .NET build/test pipeline belong to that repository; this CLI repository owns the replay service and browser viewer.
The Sessions / Forensics button in the FleetConsole attached-fleet toolbar discovers or auto-starts the replay service and opens its token-bearing launch URL in the system browser. No manual --forensic-viewer invocation is needed when using FleetConsole.
Security model
- Fragment-to-
sessionStoragetoken authentication. The launch URL carries the bearer token in the#fragment(never sent to the server). The browser app moves it tosessionStorageand strips the fragment from the URL. All API requests requireAuthorization: Bearer <token>. - Localhost-only binding (
127.0.0.1). The service is never reachable from the network. - Strict CSP, CORS origin check, host validation,
X-Frame-Options: DENY, and no request bodies accepted. - A stale descriptor from a crashed service is cleaned up on the next
--forensic-viewerrun after a failed health probe, and on ordinaryagents-fleetstartup by a best-effort sweep (see below).
Stale descriptor sweep on startup
Normal agents-fleet startup runs a best-effort sweep that unlinks a descriptor left behind by a crashed viewer, so ~/.fleet/forensics/viewer-server.json does not linger with a dead PID and mislead the next reader. (Windows recycles PIDs, so Get-Process -Id <pid> on a stale descriptor can show a live but entirely unrelated process.)
The sweep never throws and never blocks boot. When no descriptor file exists it costs one failed read plus one existence check and makes no network call — the PID check and the authenticated /api/health probe run only when a descriptor is actually present, and that probe is bounded by a 1-second socket timeout. Because it can touch localhost at all, it is killswitched:
AGENTS_FLEET_FORENSIC_VIEWER_SWEEP=0 agents-fleetDefault is on; only 0 or false (trimmed, case-insensitive) disables it — any other value, including a typo, leaves it on.
Windows NTFS ACL caveat
Both the ledger files and the descriptor file are created with POSIX mode bits — ledgers at 0o600 and their containing directories at 0o700 (src/forensics/ForensicEventLedger.ts), and the descriptor at 0o600. Node.js mode bits are not enforced by NTFS ACLs on Windows; these files simply inherit parent-folder permissions.
Consequence on Windows: the full, unredacted conversation history in ~/.fleet/sessions/*.events.ndjson is readable by any local user unless you restrict the directory yourself. The ledgers are considerably more sensitive than the descriptor. Apply appropriate ACLs to both ~/.fleet/sessions/ and ~/.fleet/forensics/ on Windows.
Retention
Ledgers are not deleted at session end. They are reaped at the next startup on two dimensions:
| Dimension | Default | Variable |
|---|---|---|
| Age window | 30 days | AGENTS_FLEET_SESSION_TELEMETRY_RETENTION_DAYS |
| Total budget across all ledgers (oldest-first) | 2048 MB | AGENTS_FLEET_SESSION_TELEMETRY_MAX_TOTAL_MB |
The budget is what actually bounds the worst case. An age window alone cannot stop a burst of long sessions inside a single window that each saturate the 50 MB AGENTS_FLEET_SESSION_TELEMETRY_MAX_MB per-session cap.
For scale: a real short-session ledger measures ~51 KB, so a typical operator never reaches either limit — but at the per-session cap the same session count would be three orders of magnitude larger, which is why both limits exist.
Set either variable to 0 to disable that dimension and take retention back yourself. Reaping is best-effort: a ledger held open by a running viewer or another process is skipped, never a fatal error. The live session's own ledger is never reaped.
Environment variable reference
| Variable | Default | Description |
|---|---|---|
AGENTS_FLEET_SESSION_TELEMETRY | on | Full-payload forensic event capture. Set to 0 or false to opt out; any other value keeps it on. |
AGENTS_FLEET_SESSION_TELEMETRY_MAX_MB | 50 | Maximum ledger file size in megabytes. |
AGENTS_FLEET_SESSION_TELEMETRY_RETENTION_DAYS | 30 | Startup reaper age window. 0 disables. |
AGENTS_FLEET_SESSION_TELEMETRY_MAX_TOTAL_MB | 2048 | Startup reaper total budget across all ledgers, trimmed oldest-first. 0 disables. |
AGENTS_FLEET_FORENSIC_VIEWER_DESCRIPTOR | ~/.fleet/forensics/viewer-server.json | Override the descriptor file path. |
AGENTS_FLEET_FORENSIC_VIEWER_SWEEP | on | Best-effort startup sweep that unlinks a stale viewer descriptor. Set to 0 or false to opt out; any other value keeps it on. |
See also: Configuration reference.