Tracing Overview
Tracing gives you full visibility into what your AI application is doing at every step. Each request flows through multiple stages — LLM calls, tool invocations, retrieval lookups, orchestration logic — and tracing captures all of them as a structured timeline you can inspect, debug, and optimize.Why Tracing Matters for AI Applications
Traditional application monitoring tracks HTTP requests and database queries. AI applications introduce new challenges:- Non-deterministic outputs — The same prompt can produce different results across runs
- Multi-step orchestration — Agents chain multiple LLM calls, tool uses, and retrieval steps together
- Cost and latency visibility — Token usage and model latency vary per request and need tracking
- Debugging complex chains — When an agent fails on step 7 of 12, you need to see the full execution path
Core Concepts
Traces
A trace represents a single end-to-end request through your application. It is identified by a uniquetraceId and contains one or more spans arranged in a parent-child hierarchy.
Spans
A span represents a single operation within a trace. Each span captures:- Name — What this operation does (e.g., “generate-response”, “search-docs”)
- Kind — The category of operation (see SpanKind below)
- Input / Output — Structured data flowing through the operation
- Metrics — Token counts, cost, latency, model information
- Status — Whether the operation succeeded (
ok), failed (error), or is in progress (unset) - Duration — How long the operation took
- Attributes — Custom key-value metadata
Parent-Child Relationships
Spans form a tree. When a span is created while another span is active, the new span automatically becomes a child of the active span. This gives you a hierarchical view of your application’s execution: Context propagation is handled automatically usingAsyncLocalStorage (TypeScript) or contextvars (Python), so child spans are linked to their parents without any manual wiring.
SpanKind Taxonomy
Every span has akind that classifies the type of operation it represents. MutagenT defines 15 span kinds, aligned with the OpenTelemetry Gen AI semantic conventions (v1.37+):
Generation
| Kind | Description | Example Use |
|---|---|---|
llm.chat | Chat completion call | OpenAI chat.completions.create() |
llm.completion | Text completion call | Legacy completion APIs |
llm.embedding | Embedding generation | Creating vector embeddings for search |
Orchestration
| Kind | Description | Example Use |
|---|---|---|
chain | Sequential pipeline of steps | LangChain chain, RAG pipeline |
agent | Autonomous agent execution | ReAct agent, tool-using agent |
graph | Graph-based execution | LangGraph, state machine workflows |
node | Single node in a graph | Individual graph node execution |
edge | Transition between graph nodes | Conditional routing logic |
workflow | Multi-step workflow | Mastra workflow, orchestration flow |
middleware | Request/response middleware | Input validation, output formatting |
Tools
| Kind | Description | Example Use |
|---|---|---|
tool | External tool invocation | Function calling, API calls, code execution |
Retrieval
| Kind | Description | Example Use |
|---|---|---|
retrieval | Document/data retrieval | Vector store query, database lookup |
rerank | Result re-ranking | Cross-encoder reranking of search results |
Safety
| Kind | Description | Example Use |
|---|---|---|
guardrail | Safety or policy check | Content moderation, PII detection |
Other
| Kind | Description | Example Use |
|---|---|---|
custom | Any operation not covered above | Custom business logic |
How Tracing Works
Automatic Tracing with Integration Packages
If you use one of MutagenT’s integration packages (@mutagent/langchain, @mutagent/langgraph, @mutagent/openai, @mutagent/vercel-ai, @mutagent/mastra), tracing happens automatically. The integration intercepts framework callbacks and creates properly structured spans without any manual instrumentation.
Manual Tracing with the SDK
When you need fine-grained control, or when building custom orchestration logic, use the SDK’s tracing API directly. MutagenT provides three levels of abstraction:Decorators -- Class method instrumentation
Decorators -- Class method instrumentation
Use the
@trace() decorator to automatically wrap class methods with span creation, input/output capture, and error handling.Wrappers -- Function-level instrumentation
Wrappers -- Function-level instrumentation
Use
withTrace() to wrap any function with a span and get a SpanHandle for manual enrichment.Low-level API -- Full manual control
Low-level API -- Full manual control
Use
startSpan() and endSpan() for maximum flexibility, typically in integration adapters.Architecture
The tracing pipeline follows a simple, non-blocking flow from your application to the MutagenT API: The API also accepts traces from OpenTelemetry-compatible exporters via the OTLP bridge endpoint (POST /api/traces/otlp), which normalizes ExportTraceServiceRequest payloads into the MutagenT format before storing them.
Key design decisions:
- Non-blocking — Span collection never blocks your application. Spans are buffered in memory and flushed asynchronously.
- Batch transport — Spans are grouped by trace ID and sent in batches to minimize HTTP overhead. Default: flush every 5 seconds or when 10 spans accumulate.
- Retry with backoff — Failed flushes are retried with exponential backoff (up to 3 retries, base delay 1s doubling each retry).
- Graceful shutdown —
shutdownTracing()flushes all remaining spans before the process exits. - Lazy initialization — If
MUTAGENT_API_KEYis set in the environment, tracing initializes automatically on the firststartSpan()call without requiring an explicitinitTracing(). - Hybrid OTel strategy — MutagenT uses a lean native schema with
gen_ai.*OTel semantic conventions (v1.37+) plusmutagent.*extensions, and provides an OTLP bridge for any OTel-compatible exporter. - Idempotent ingestion — Traces and spans use upsert semantics, so re-sending the same trace ID updates rather than duplicates.
When to Use What
| Scenario | Approach |
|---|---|
| Using LangChain, LangGraph, Vercel AI, OpenAI, or Mastra | Use the integration package — tracing is automatic |
| Custom orchestration logic | Use withTrace() for function-level spans |
| Class-based agent architecture | Use @trace() decorator on methods |
| Building a framework integration | Use the low-level startSpan() / endSpan() API |
| Simple scripts or one-off calls | Use withTrace() for quick instrumentation |
| OTel-compatible exporter already in use | Send traces to the OTLP bridge endpoint (POST /api/traces/otlp) |
Next Steps
Tracing Setup
Configure tracing in your application with initTracing() and environment variables.
Tracing API Reference
Full reference for decorators, wrappers, and low-level span primitives.