Maniac Docs
Streaming & tracing

Tracer

In-memory TraceEvent collector with emit, aiter replay, and TraceKind event kinds used by the agent runner.

Tracer

Tracer is the in-memory event collector the runner uses for every agent run. It assigns run_id, seq, and event_id, buffers the full history in tracer.events, and fans out live events to async subscribers via aiter().

import { Tracer, runAgent } from "@maniac-ai/agents";

const tracer = new Tracer({ run_id: "support-turn-7" });
const result = await runAgent(spec, "Reset my password", { tracer });

console.log(result.trace.length); // same as tracer.events.length

Pass the same tracer into runAgentStream so streaming consumers and the final AgentResult share one buffer. BackgroundTaskDispatcher gives each child task its own tracer and merges events into the parent dispatcher tracer.

emit

tracer.emit(kind, payload, options);
  • kind — a TraceKind discriminator (see table below)
  • payload — typed JSON payload for that kind (nested under event.payload)
  • options — envelope overrides: depth, principal, span_id, parent_span_id, turn_id, message_id, thread_id, token-specific delta / chunk_kind, etc.

The tracer overwrites seq, event_id, and run_id on every emit so producers cannot break ordering invariants.

aiter and replay

runAgentStream calls tracer.enableStreaming() then iterates tracer.aiter(). Each subscription:

  1. Replays every event already buffered (late subscribers never miss history)
  2. Yields live events as they are emitted
  3. Terminates when tracer.close() sends a sentinel

One consumer per aiter() call is recommended — async generators cannot be multiplexed across multiple awaiters.

const tracer = new Tracer();
tracer.enableStreaming();

const run = runAgent(spec, query, { tracer });

for await (const event of tracer.aiter()) {
  if (event.kind === "final") break;
  handle(event);
}

const result = await run;

Trace kinds

kindTypical use
lm_call_start / lm_callModel request/response pair per iteration
tokenStreaming text, reasoning, or structured partials
tool_call_arguments_deltaStreaming tool-call JSON args
toolTool invocation result (includes result_preview when completed)
stepStep hook before/after/stopped
guardrailBlock or rewrite from LM/tool guardrails
approvalHITL approval requested
agent / subagentInner-agent boundary
memoryConversation / observation / working-memory writes
retryRetryingModel / FallbackModel attempt
cellPython REPL execution
background_taskDispatcher lifecycle
planPlan primitive updates (ACP)
final / errorTerminal run outcome

Switch on event.kind for typed narrowing — payloads are validated by Zod schemas in @maniac-ai/agents/schemas.

AgentResult.trace

runAgent returns result.trace as a snapshot of tracer.events at completion. Errored and cancelled runs still populate trace (and often messages) from the partial run via RunCancelledError.partial.

Integration points

  • Inference adaptersRetryingModel and FallbackModel accept an optional tracer and emit retry events
  • Memory stores — pass { tracer } on write methods to emit memory events
  • Middleware / guardrails — blocked decisions emit guardrail events (see Guardrails)
  • OTelTracer — wraps Tracer and translates the same stream to spans (see OTelTracer)

On this page