Debugging
An agent gives the wrong answer in production. The first 30 seconds of debugging matter most — was it the prompt? The tool result? A memory injection? A skill activation? agentfootprint exposes every one of those decisions as a typed event, recorded during the run, replayable later. You don’t reconstruct what happened from logs; you read the trace.
Three layers of debug surface
Section titled “Three layers of debug surface”| Surface | When to use |
|---|---|
| Typed event listeners | Mid-run debugging in tests / dev — agent.on('*', ...) for every event, or agent.on('agentfootprint.stream.*', ...) per-domain |
| Narrative recorder | Post-run human-readable trace (“what happened, in order”) |
| Time-travel checkpoint | Replay decisions cross-process, cross-day (Causal memory snapshot) |
Live status — enable.thinking
Section titled “Live status — enable.thinking”For interactive debugging in terminal:
agent.enable.thinking({ onStatus: (s) => console.log(`⎈ ${s}`),});Prints one line per state transition — “calling LLM… tool weather(SF)… LLM… done”. The Claude-Code-style live status. Drop into your dev script.
Structured logs — enable.logging
Section titled “Structured logs — enable.logging”For CI / staging environments:
import { LoggingDomains } from 'agentfootprint';
agent.enable.logging({ domains: [LoggingDomains.STREAM, LoggingDomains.AGENT, LoggingDomains.CONTEXT], logger: pino(), // or console, winston, etc.});Filters the firehose to specific event domains; pipes to your structured logger.
Targeted event subscription
Section titled “Targeted event subscription”For specific concerns:
agent.on('agentfootprint.context.injected', (e) => { // Every Skill / Steering / Instruction / Fact / Memory / RAG that activates console.log(`[ctx] ${e.payload.source} → ${e.payload.slot}`);});
agent.on('agentfootprint.permission.denied', (e) => { console.log(`[BLOCKED] ${e.payload.toolName}: ${e.payload.reason}`);});
agent.on('agentfootprint.cost.tick', (e) => { console.log(`[$] +${e.payload.estimatedUsd} (cum ${e.payload.cumulative.estimatedUsd})`);});47 typed events across 13 domains. Your IDE auto-completes payload shapes per event name. See Observability guide for the full taxonomy.
Cross-run replay — Causal memory
Section titled “Cross-run replay — Causal memory”For “why did the agent make that decision two weeks ago?”:
import { defineMemory, MEMORY_TYPES, MEMORY_STRATEGIES, SNAPSHOT_PROJECTIONS } from 'agentfootprint';
const causal = defineMemory({ id: 'causal', type: MEMORY_TYPES.CAUSAL, strategy: { kind: MEMORY_STRATEGIES.TOP_K, topK: 1, threshold: 0.7, embedder }, store, projection: SNAPSHOT_PROJECTIONS.DECISIONS,});
agent.memory(causal);Every run persists its decision evidence as a snapshot. Two weeks later, when the customer comes back asking why, the matching snapshot loads into the next prompt. The follow-up answer is grounded in the EXACT past facts — not reconstruction. See Memory guide § Causal.
Agent playground (visual time-travel)
Section titled “Agent playground (visual time-travel)”Coming in v2.4 Phase 3 — a deep-link from any recorded trace into the agent playground for visual time-travel debugging. Until then, the typed events + Causal memory are the textual equivalents.
Anti-patterns
Section titled “Anti-patterns”- Don’t
console.loginside toolexecute. Subscribe toagentfootprint.stream.tool_*events instead — typed, filterable, sinkable. - Don’t try to reconstruct what happened from
JSON.stringify(agent). Use the typed event stream — the agent’s internal state isn’t a stable inspection surface. - Don’t enable EVERY event domain in production. Filter. Logs add up.
Next steps
Section titled “Next steps”- Observability guide — the full event taxonomy
- Memory guide — Causal memory for cross-run debugging
- Testing guide — mocks-first means most bugs surface in CI, not prod