apps/opik-documentation/documentation/fern/docs-v2/tracing/concepts.mdx
Opik's tracing system gives you full visibility into what your LLM application or agent is doing — every call, every step, every intermediate result. There are three building blocks you need to understand:
A trace represents a complete execution path for a single interaction with an LLM or agent. Think of it as a detailed record of everything that happened during one request-response cycle — inputs, outputs, timing, token usage, and any intermediate steps.
A span represents an individual operation or step within a trace. While a trace shows the complete picture, spans break it down into measurable components. Spans are hierarchical — they can contain other spans, creating a tree structure within the trace.
Trace: "Customer Support Chat"
├── Span: "Parse User Intent"
├── Span: "Query Knowledge Base"
│ ├── Span: "Search Vector Database"
│ └── Span: "Rank Results"
├── Span: "Generate Response"
│ ├── Span: "LLM Call: GPT-4"
│ └── Span: "Post-process Response"
└── Span: "Log Interaction"
A thread is a collection of related traces that form a coherent conversation or multi-turn workflow. Threads are essential for chat applications and agents where context evolves across multiple interactions.
Threads are created by setting a thread_id on your traces:
import opik
client = opik.Opik()
client.trace(
name="chat-turn-1",
thread_id="user-session-abc123",
input={"message": "Hello"},
output={"response": "Hi! How can I help?"},
)