A local-first recorder and replay UI for multi-step AI agent runs. It turns decisions, tool calls, results, retries, and errors into a reviewable timeline while recursively redacting common credential fields by default.
The project has no runtime dependencies and does not send traces anywhere. The viewer binds to localhost unless you explicitly choose another host.
- a small Node.js SDK with a versioned JSON event format;
- ordered events for decisions, messages, tool calls/results, retries, and errors;
- recursive key-based redaction for passwords, tokens, authorization headers, cookies, sessions, credentials, and private keys;
- inline protection for bearer values, common query-string secrets, and recognizable provider token shapes;
- a responsive local replay UI with import, filters, previous/next, autoplay, speed control, event detail, and redacted export;
- a failed two-attempt trace that makes retry behavior easy to inspect;
- CLI validation, sanitization, summaries, and a local static server;
- automated tests and GitHub Actions CI.
Requires Node.js 20 or newer.
npm install
npm startOpen http://127.0.0.1:4173. The bundled failed-search trace loads automatically. Use Import JSON for your own trace, step through the timeline, then use Export redacted to save the copy currently shown.
import { TraceRecorder } from "agent-trace-replay";
const trace = new TraceRecorder({
title: "Support answer run",
metadata: { agent: "support-agent", environment: "staging" }
});
trace.message("Task received", { request: "Find the refund window" });
trace.decision("Use policy search", {
basis: "The policy corpus is the authoritative source"
});
trace.toolCall("policy.search", {
query: "refund window",
authorization: process.env.SEARCH_AUTH
});
trace.toolResult("policy.search", { matches: 3 }, {
status: "succeeded",
durationMs: 184
});
const safeTrace = trace.finish("succeeded");The authorization value is replaced with [REDACTED] when the event is recorded. The recorder clones outputs, so it does not mutate caller-owned objects.
Capture concise decision bases and observable state, not hidden chain-of-thought. External text and tool output should be treated as untrusted data.
Run the complete deterministic sample:
npm run exampleIt prints a redacted trace that can be saved as JSON and imported into the viewer.
Each trace uses schemaVersion: 1 and contains ordered events:
{
"schemaVersion": 1,
"traceId": "trace-example",
"title": "Support answer run",
"startedAt": "2026-07-21T12:00:00.000Z",
"endedAt": "2026-07-21T12:00:04.000Z",
"status": "succeeded",
"metadata": { "agent": "support-agent" },
"events": [
{
"id": "event-0001",
"sequence": 1,
"timestamp": "2026-07-21T12:00:01.000Z",
"type": "decision",
"name": "Use policy search",
"status": "info",
"durationMs": 0,
"data": { "basis": "The policy corpus is authoritative" }
}
]
}Trace statuses are running, succeeded, failed, or cancelled. Event types are decision, tool_call, tool_result, retry, error, and message.
# Check schema and sequence integrity
node ./bin/agent-trace.js validate --input trace.json
# Redact an imported trace again before sharing it
node ./bin/agent-trace.js sanitize --input raw.json --output safe.json
# Print a compact run summary
node ./bin/agent-trace.js summary --input safe.json
# Serve the replay UI locally
node ./bin/agent-trace.js serve --host 127.0.0.1 --port 4173The server exposes only four allowlisted assets, sends a restrictive Content Security Policy, and never interprets imported trace values as HTML or code.
Default redaction is a safety net, not a proof that arbitrary data is free of sensitive information. It covers common credential keys and token patterns. Product-specific personal data or proprietary fields should be added to your own collection boundary before recording, and exported traces should still be reviewed before sharing.
npm test
npm run check:exampleTests cover recursive redaction, immutable inputs, ordered recording, failure/retry preservation, invalid sequence rejection, CLI sanitization and summaries, and the local server allowlist.
Apache-2.0