Skip to main content

Observability

4 min read

Debug Timeline

AI-specific event log with snapshot correlation for time-travel debugging.

The debug timeline records agent lifecycle events (start, complete, error, guardrails, approvals, handoffs, patterns) and correlates them with core time-travel snapshots. Zero-cost when debug: false – the timeline is simply null.


Quick Start

Enable the timeline by passing debug to either orchestrator:

import { createAgentOrchestrator } from '@directive-run/ai';

const orchestrator = createAgentOrchestrator({
  runner,
  debug: true,
});

await orchestrator.run(agent, 'Hello!');

// Access the timeline
const events = orchestrator.timeline?.getEvents();

Both createAgentOrchestrator and createMultiAgentOrchestrator expose a timeline property when debug is enabled.


Event Types

The timeline records the following event types covering the full agent lifecycle:

EventWhen it fires
agent_startAgent run begins
agent_completeAgent run succeeds
agent_errorAgent run fails
agent_retryAgent retries after failure
guardrail_checkGuardrail evaluates input/output
constraint_evaluateDirective constraint fires
resolver_startResolver begins execution
resolver_completeResolver completes
resolver_errorResolver fails
approval_requestApproval workflow triggered
approval_responseApproval granted/denied
handoff_startAgent handoff begins
handoff_completeAgent handoff completes
pattern_startExecution pattern begins
pattern_completeExecution pattern completes
dag_node_updateDAG node status changes
breakpoint_hitBreakpoint fires and pauses execution
breakpoint_resumedBreakpoint resumed or cancelled
derivation_updateCross-agent derivation recomputed
scratchpad_updateShared scratchpad value changed
reflection_iterationReflection iteration completed
race_startRace pattern begins
race_winnerRace pattern winner selected
race_cancelledRace pattern loser cancelled
debate_roundDebate round completed
checkpoint_savePattern checkpoint saved
checkpoint_restorePattern checkpoint restored

Every event includes id, type, timestamp, and snapshotId (for time-travel correlation). Agent-scoped events also include agentId.

Event Data Shapes

Each event type carries specific data fields beyond the common base:

Agent lifecycle events:

  • agent_startinputLength
  • agent_completeoutputLength, totalTokens, durationMs
  • agent_errorerrorMessage, durationMs
  • agent_retryattempt, errorMessage, delayMs

Guardrail and constraint events:

  • guardrail_checkguardrailName, guardrailType (input/output/toolCall), passed, reason?
  • constraint_evaluateconstraintId, fired

Resolver events:

  • resolver_startresolverId, requirementType
  • resolver_completeresolverId, requirementType, durationMs
  • resolver_errorresolverId, requirementType, errorMessage

Approval events:

  • approval_requestrequestId, toolName?
  • approval_responserequestId, approved, reason?

Pattern events:

  • pattern_startpatternId, patternType
  • pattern_completepatternId, patternType, durationMs, error?

Handoff events:

  • handoff_startfromAgent, toAgent, handoffId
  • handoff_completefromAgent, toAgent, handoffId, durationMs

DAG events:

  • dag_node_updatenodeId, status, durationMs?

Breakpoint events:

  • breakpoint_hitbreakpointId, breakpointType, label?
  • breakpoint_resumedbreakpointId, modified, skipped

Cross-agent state events:

  • derivation_updatederivationId, value
  • scratchpad_updatekey, value

Reflection events:

  • reflection_iterationiteration, score, feedback?, durationMs

Race events:

  • race_startagents (string array)
  • race_winnerwinnerId, durationMs
  • race_cancelledcancelledAgents (string array)

Debate events:

  • debate_roundround, winnerId, score?, agentCount

Checkpoint events:

  • checkpoint_savecheckpointId, patternType, step
  • checkpoint_restorecheckpointId, patternType, step

Querying Events

const timeline = orchestrator.timeline!;

// All events in order
const all = timeline.getEvents();

// Events for a specific agent
const agentEvents = timeline.getEventsForAgent('researcher');

// Events by type (type-narrowed)
const errors = timeline.getEventsByType('agent_error');
// errors[0].errorMessage – TypeScript knows the shape

// Events at a specific snapshot
const atSnapshot = timeline.getEventsAtSnapshot(5);

// Events in a time range
const recent = timeline.getEventsInRange(Date.now() - 10000, Date.now());

Snapshot Correlation

Each event stores a snapshotId that links it to a core time-travel snapshot. Events that cause fact changes get the latest snapshot ID; events without fact changes (like guardrail checks) get snapshotId: null.

// Find what happened at snapshot 7
const events = timeline.getEventsAtSnapshot(7);

// Walk backwards from the latest snapshot
const allEvents = timeline.getEvents();
const grouped = Object.groupBy(allEvents, (e) => e.snapshotId ?? 'no-snapshot');

Fork and Replay

Truncate the timeline at a snapshot point and replay from there:

// Fork from snapshot 5 – truncates events after that point
// and navigates the system back to snapshot 5
timeline.forkFrom(5);

// Re-run the agent – new events append automatically
await orchestrator.run(agent, 'Try a different approach');

This calls system.debug.goTo(snapshotId) under the hood, restoring the full system state.


Export and Import

Serialize the timeline for persistence or sharing:

// Export as JSON
const json = timeline.export();
localStorage.setItem('debug-session', json);

// Import from JSON
const saved = localStorage.getItem('debug-session');
if (saved) {
  timeline.import(saved);
}

Import validates all events and enforces the maxEvents cap.


Standalone Usage

Create a timeline without an orchestrator for custom instrumentation:

import { createDebugTimeline, createDebugTimelinePlugin } from '@directive-run/ai';

const timeline = createDebugTimeline({ maxEvents: 1000 });

// Record custom events
timeline.record({
  type: 'agent_start',
  timestamp: Date.now(),
  agentId: 'my-agent',
  snapshotId: null,
  inputLength: 42,
});

// Bridge core constraint/resolver events
const plugin = createDebugTimelinePlugin(timeline, () => system.debug?.currentIndex ?? null);

Multi-Agent Timeline

In a multi-agent orchestrator, every event includes agentId, making it easy to build per-agent timelines:

const multi = createMultiAgentOrchestrator({
  runner,
  agents: { researcher: { agent: researcher }, writer: { agent: writer } },
  debug: true,
});

await multi.runPattern('research-and-write', 'Explain WASM');

// Per-agent view
const researcherEvents = multi.timeline!.getEventsForAgent('researcher');
const writerEvents = multi.timeline!.getEventsForAgent('writer');

// Pattern-level view
const patternStarts = multi.timeline!.getEventsByType('pattern_start');

Configuration

OptionDefaultDescription
maxEvents2000Ring buffer size – oldest events evicted first
getSnapshotIdCallback to read current snapshot ID
goToSnapshotCallback for forkFrom() navigation

Privacy

Events store inputLength and outputLength, never full content. Error messages are included since they are developer-facing. Token usage is recorded as totalTokens.


Next Steps

Previous
Semantic Cache

We care about your data. We'll never share your email.

Powered by Directive. This signup uses a Directive module with facts, derivations, constraints, and resolvers – zero useState, zero useEffect. Read how it works

Directive - Constraint-Driven State Management for TypeScript