Skip to main content

Tracing

The @mutagent/sdk/tracing module provides custom instrumentation primitives for tracing LLM calls, agent workflows, tool usage, and more. Use it when the Integration packages do not cover your framework, or when you need fine-grained control over span creation.
For concepts, span kinds, and the overall tracing architecture, see the Tracing Overview. For the full server-side API reference, see the Tracing API.

Installation

The tracing module is included in @mutagent/sdk. No additional packages are required.
npm install @mutagent/sdk

Quick Start

import { initTracing, shutdownTracing } from '@mutagent/sdk/tracing';

// Initialize once at application startup
initTracing({
  apiKey: process.env.MUTAGENT_API_KEY!,
  environment: 'production',
  debug: false,
});

// ... your application code using @trace, withTrace, or startSpan ...

// Shutdown gracefully (flushes remaining spans)
await shutdownTracing();

Lazy Initialization

If you do not call initTracing() explicitly, the module automatically initializes from the MUTAGENT_API_KEY environment variable on the first startSpan() call. This is a one-time attempt — if the variable is not set, tracing remains disabled for the rest of the process lifecycle.
// No initTracing() call needed if MUTAGENT_API_KEY is set
import { startSpan, endSpan } from '@mutagent/sdk/tracing';

// First call triggers lazy init from env var
const span = startSpan({ kind: 'llm.chat', name: 'openai-chat' });

Architecture

The tracing module uses a singleton architecture:
  • SpanManager — Creates and manages spans with AsyncLocalStorage for parent-child propagation
  • BatchCollector — Buffers finished spans in memory and flushes when either the batch size (default 10) or the flush interval (default 5s) is reached. Retries with exponential backoff on failure (up to 3 attempts).
  • TraceHTTPClient — Sends grouped span payloads to POST /api/traces

Instrumentation Approaches

The SDK provides three levels of instrumentation, from highest to lowest abstraction.

1. withTrace() Wrapper

The primary instrumentation API. Wraps any function with a tracing span and provides a SpanHandle for manual enrichment during execution.
import { withTrace } from '@mutagent/sdk/tracing';

const result = await withTrace(
  { kind: 'chain', name: 'rag-pipeline' },
  async (span) => {
    span.setAttributes({ 'rag.corpus': 'knowledge-base-v2' });

    const docs = await retrieve(query);
    span.addEvent('retrieval-complete', { documentCount: docs.length });

    const answer = await generate(query, docs);
    span.setOutput({ text: answer });
    span.setMetrics({
      model: 'gpt-4o',
      provider: 'openai',
      inputTokens: 150,
      outputTokens: 300,
      totalTokens: 450,
    });

    return answer;
  }
);
When tracing is not initialized, withTrace runs the function directly with a no-op SpanHandle — your code executes normally without any overhead.

Wrapper Options

interface WithTraceOptions {
  kind: SpanKind;                        // Required: span kind
  name?: string;                         // Span name
  input?: SpanIO;                        // Initial structured input
  attributes?: Record<string, unknown>;  // Custom attributes
}

SpanHandle Methods

MethodDescription
setAttributes(attrs)Add custom key-value attributes to the span
addEvent(name, attrs?)Record a lifecycle event with timestamp and optional attributes
setOutput(output)Set structured output (SpanIO)
setInput(input)Set or override structured input (SpanIO)
setMetrics(metrics)Set token counts, cost, latency, and model info
spanIdRead-only span ID
traceIdRead-only trace ID

2. @trace() Decorator

For class-based code. Automatically captures method arguments as input and the return value as output. Requires experimentalDecorators: true in tsconfig.json.
import { trace } from '@mutagent/sdk/tracing';

class MyAgent {
  @trace({ kind: 'agent', name: 'research-agent' })
  async run(query: string): Promise<string> {
    // Your agent logic here
    return result;
  }

  @trace({ kind: 'tool', name: 'web-search' })
  async search(query: string): Promise<string[]> {
    // Tool implementation
    return results;
  }
}
The decorator:
  • Creates a span with the specified kind and name
  • If name is omitted, falls back to the method name, then the kind
  • Captures arguments as input.raw and the return value as output.raw
  • Sets status: 'ok' on success, status: 'error' on exceptions (with message)
  • Propagates parent-child span relationships via AsyncLocalStorage context
  • Works with both sync and async methods, preserving this context
  • No-ops gracefully when tracing is not initialized

Decorator Options

interface TraceDecoratorOptions {
  kind: SpanKind;                        // Required: span kind
  name?: string;                         // Span name (defaults to method name)
  attributes?: Record<string, unknown>;  // Custom attributes
}

3. startSpan() / endSpan() Manual API

The lowest-level API for integration adapters or scenarios where automatic span lifecycle does not fit.
import {
  startSpan,
  endSpan,
  runInSpanContext,
  getCurrentSpan,
  getCurrentTraceId,
} from '@mutagent/sdk/tracing';

const span = startSpan({
  kind: 'llm.chat',
  name: 'openai-chat',
  input: {
    messages: [
      { role: 'user', content: 'Hello!' },
    ],
  },
});

if (span) {
  // Run nested code within span context (enables parent-child propagation)
  const result = await runInSpanContext(span, async () => {
    // getCurrentSpan() returns this span inside the callback
    // getCurrentTraceId() returns the active trace ID
    const response = await callLLM();

    endSpan(span, {
      status: 'ok',
      output: {
        messages: [
          { role: 'assistant', content: response.text },
        ],
      },
      metrics: {
        model: 'gpt-4o',
        provider: 'openai',
        inputTokens: response.usage.prompt_tokens,
        outputTokens: response.usage.completion_tokens,
        totalTokens: response.usage.total_tokens,
      },
    });

    return response;
  });
}

Low-Level API Functions

FunctionDescription
startSpan(options)Create a new span. Returns MutagentSpan | undefined
endSpan(span, endOptions?)End a span, compute duration, deliver to batch collector
runInSpanContext(span, fn)Run fn within the span’s async context for parent-child propagation
getCurrentSpan()Get the active span from async context
getCurrentTraceId()Get the active trace ID from async context

SpanOptions

interface SpanOptions {
  kind: SpanKind;                        // Required: span kind
  name?: string;                         // Span name
  input?: SpanIO;                        // Structured input
  attributes?: Record<string, unknown>;  // Custom attributes
  parentSpanId?: string;                 // Explicit parent span (auto-inferred from context if omitted)
}

SpanEndOptions

interface SpanEndOptions {
  status?: SpanStatus;                   // 'ok' | 'error' | 'unset'
  statusMessage?: string;                // Error message or status detail
  output?: SpanIO;                       // Structured output
  metrics?: SpanMetrics;                 // Token counts, cost, latency
  attributes?: Record<string, unknown>;  // Additional attributes
  events?: SpanEvent[];                  // Lifecycle events
}

Configuration Reference

The initTracing() function accepts a TracingConfig object:
PropertyTypeDefaultDescription
apiKeystring— (required)MutagenT API key for authentication
endpointstringhttps://api.mutagent.ioAPI endpoint URL
environmentstringEnvironment name (e.g., production, staging)
batchSizenumber10Number of spans to buffer before flushing
flushIntervalMsnumber5000Flush interval in milliseconds
debugbooleanfalseLog span start/end events to console
sourcestringsdkSource identifier for traces

Lifecycle Functions

FunctionDescription
initTracing(config)Initialize tracing. Idempotent: calling again replaces the previous configuration (shuts down the old collector first).
shutdownTracing()Flush remaining spans, clear timers, and reset singleton state. Returns a Promise<void>.
isTracingInitialized()Check whether tracing has been initialized. Returns boolean.

Type Reference

SpanKind

Taxonomy aligned with OTel Gen AI semantic conventions (v1.37+):
CategoryValues
Generationllm.chat, llm.completion, llm.embedding
Orchestrationchain, agent, graph, node, edge, workflow, middleware
Toolstool
Retrievalretrieval, rerank
Safetyguardrail
Othercustom

SpanIO

Structured input/output for spans:
FieldTypeDescription
messagesArray<{ role, content, name?, toolCallId? }>Chat messages (most common for LLM spans). Roles: system, user, assistant, tool
toolCallsArray<{ id, name, arguments, result? }>Tool calls for LLM spans requesting tool use
documentsArray<{ content, metadata?, score? }>Retrieved documents (for retrieval spans)
textstringRaw text (for completions, generic spans)
rawunknownFramework-specific data (escape hatch)

SpanStatus

'ok' | 'error' | 'unset'

SpanMetrics

FieldTypeDescription
modelstringModel identifier (e.g., gpt-4o, claude-sonnet-4)
providerstringProvider name (e.g., openai, anthropic)
inputTokensnumberInput token count
outputTokensnumberOutput token count
totalTokensnumberTotal token count
costUsdnumberEstimated cost in USD
latencyMsnumberTotal latency in milliseconds
ttftMsnumberTime to first token in milliseconds

SpanEvent

FieldTypeDescription
namestringEvent name
timestampDateWhen the event occurred (auto-set by addEvent)
attributesRecord<string, unknown>Optional event attributes

MutagentSpan

Internal mutable span representation (returned by startSpan):
FieldTypeDescription
idstringUnique span ID
traceIdstringTrace ID this span belongs to
parentSpanIdstring | undefinedParent span ID (if nested)
kindSpanKindSpan kind
namestringSpan name
startedAtDateWhen the span started
inputSpanIO | undefinedStructured input
outputSpanIO | undefinedStructured output
statusSpanStatusCurrent status
statusMessagestring | undefinedError/status message
metricsSpanMetricsToken counts, cost, etc.
attributesRecord<string, unknown>Custom attributes
eventsSpanEvent[]Lifecycle events

FinishedSpan

Immutable span ready for serialization and transport:
FieldTypeDescription
spanIdstringUnique span ID
traceIdstringTrace ID
parentSpanIdstring | undefinedParent span ID
namestringSpan name
kindSpanKindSpan kind
startTimestringISO 8601 start time
endTimestringISO 8601 end time
durationMsnumberDuration in milliseconds
statusSpanStatusFinal status
statusMessagestring | undefinedError/status message
modelstring | undefinedModel used
providerstring | undefinedProvider name
inputTokensnumber | undefinedInput token count
outputTokensnumber | undefinedOutput token count
totalTokensnumber | undefinedTotal token count
costUsdnumber | undefinedEstimated cost

Exports Summary

All exports from @mutagent/sdk/tracing:
// Lifecycle
import {
  initTracing,
  shutdownTracing,
  isTracingInitialized,
} from '@mutagent/sdk/tracing';

// Decorator
import { trace } from '@mutagent/sdk/tracing';
import type { TraceDecoratorOptions } from '@mutagent/sdk/tracing';

// Wrapper
import { withTrace } from '@mutagent/sdk/tracing';
import type { WithTraceOptions } from '@mutagent/sdk/tracing';

// Low-level API
import {
  startSpan,
  endSpan,
  getCurrentSpan,
  getCurrentTraceId,
  runInSpanContext,
} from '@mutagent/sdk/tracing';

// Types
import type {
  SpanKind,
  SpanIO,
  SpanStatus,
  SpanEvent,
  SpanMetrics,
  SpanOptions,
  SpanEndOptions,
  SpanHandle,
  MutagentSpan,
  FinishedSpan,
  TracingConfig,
  TracePayload,
  TraceHTTPResponse,
} from '@mutagent/sdk/tracing';

Next Steps

Tracing Overview

Concepts, span hierarchy, and tracing architecture

Tracing API Reference

Full server-side API reference for ingesting and querying traces

Integrations

Framework adapters with automatic tracing (recommended for most users)

TypeScript SDK Setup

Install and configure the TypeScript SDK