ML Observe

Interactive designer

Trace Span Designer

Drag the stages of your LLM pipeline into order. We prescribe the OpenTelemetry / OpenLLMetry span name and the required + recommended attributes for each, emit a fully annotated trace schema and a runnable Python instrumentation snippet, and tell you exactly what you'll be able to debug — and where your blind spots are.

Span names and attribute keys follow the OpenTelemetry GenAI semantic conventions plus OpenLLMetry extensions. See our guide to what belongs in a span (reviewed 2026-05-12).

Stage palette — click to add

Your pipeline — reorder with ◀ ▶, ✕ to remove

Add stages from the palette above to design your trace.

Prescribed spans

#1 Retrieval

retrieval.query · CLIENT

OpenLLMetry alias: vector_db.query / db.vector.query

Embed the query and fetch candidate chunks from a vector store or search index.

Attributes

db.system = "pinecone" required

Which store answered — separates a Pinecone outage from a Weaviate one.

db.vector.query.top_k = 20 required

Recall ceiling; a low top_k is the most common silent cause of 'the answer wasn't in context'.

retrieval.query.text = "how do I rotate API keys" required

The actual query embedded — without it you cannot reproduce a bad retrieval.

retrieval.documents.count = 8 required

How many chunks actually came back (≠ top_k when the index is small or filtered).

retrieval.documents.ids = "[doc_42#3, doc_11#1]" recommended

Lets you replay the exact context and diff it across versions.

retrieval.score.min = 0.71 recommended

Score floor — a collapsing min score is an early drift signal for the index.

retrieval.filter = "tenant=acme" recommended

Metadata filter applied; a wrong filter looks identical to 'no relevant docs'.

embedding.model = "text-embedding-3-large" recommended

Query/index embedding mismatch is a classic invisible failure.

#2 Rerank

rerank.documents · CLIENT

OpenLLMetry alias: reranker.rerank

Re-score retrieved candidates with a cross-encoder or LLM judge and keep the best N.

Attributes

rerank.model = "cohere-rerank-3" required

Reranker identity — quality regressions usually track a model/version change.

rerank.input.count = 20 required

Candidates in; with output.count it reveals how aggressive the cut was.

rerank.output.count = 5 required

What actually reached the prompt — the real context budget.

rerank.top_score = 0.93 required

Confidence of the kept set; a low top score after rerank means retrieval failed upstream.

rerank.order.changed = true recommended

Did rerank actually reorder, or is it dead weight/latency?

rerank.dropped.ids = "[doc_11#1]" recommended

Lets you audit a relevant doc the reranker wrongly discarded.

rerank.score.delta = 0.22 recommended

Top-vs-cut score gap — a narrow gap means the ranking is barely meaningful.

#3 Prompt assembly

prompt.assemble · INTERNAL

OpenLLMetry alias: gen_ai.prompt (template stage)

Render the final prompt from a template, retrieved context, history, and variables.

Attributes

prompt.template.id = "rag_answer_v7" required

Which template/version produced this prompt — the #1 thing to correlate quality changes against.

prompt.token_count = 3120 required

Final assembled size; silent context truncation is a top cause of dropped answers.

prompt.context.truncated = false required

Explicit truncation flag so a cut context is loud, not silent.

prompt.variables = "{user_role: admin}" required

Injected variables — needed to reproduce the exact prompt deterministically.

prompt.context.doc_count = 5 recommended

How many chunks survived into the prompt vs how many rerank emitted.

prompt.system.hash = "sha256:9f2a…" recommended

Detects an unannounced system-prompt change across deploys.

prompt.history.turns = 4 recommended

Conversation depth — long histories crowd out retrieved context.

#4 LLM call

gen_ai.chat · CLIENT

OpenLLMetry alias: openai.chat / {provider}.chat

The model inference request itself — the canonical OpenTelemetry GenAI span.

Attributes

gen_ai.system = "openai" required

Provider — first split for latency/error/cost dashboards.

gen_ai.request.model = "gpt-4.1" required

Requested model; silent model swaps explain sudden quality/cost shifts.

gen_ai.response.model = "gpt-4.1-2026-04" required

Model actually served — providers alias and roll versions under you.

gen_ai.usage.input_tokens = 3120 required

Cost and context-pressure driver.

gen_ai.usage.output_tokens = 480 required

Cost driver and a proxy for runaway/verbose generations.

gen_ai.response.finish_reason = "stop" required

'length' here = truncated answer; the single most actionable quality field.

gen_ai.request.temperature = 0.2 recommended

Reproducibility and explaining nondeterministic regressions.

gen_ai.request.max_tokens = 512 recommended

Too-low caps cause 'length' truncation — pair with finish_reason.

gen_ai.response.id = "chatcmpl-AbC123" recommended

Provider request id for support tickets and dedup.

gen_ai.usage.cache_read_tokens = 2048 recommended

Prompt-cache hit rate — large lever on cost and latency.

#5 Tool / function call

gen_ai.execute_tool · INTERNAL

OpenLLMetry alias: {tool_name}.tool / function.call

A model-requested tool/function invocation and its result, inside an agent loop.

Attributes

gen_ai.tool.name = "get_account_balance" required

Which tool ran — agents fail at the tool boundary far more than in the model.

gen_ai.tool.call.arguments = "{account_id: 42}" required

Args the model produced — most agent bugs are malformed/hallucinated arguments.

gen_ai.tool.call.status = "ok" required

ok/error/timeout — separates a model mistake from a downstream failure.

gen_ai.tool.call.id = "call_7b2" required

Correlates the request with the result message fed back to the model.

gen_ai.tool.result.truncated = true recommended

A truncated tool result silently degrades the next model turn.

gen_ai.tool.call.retries = 1 recommended

Retry loops are a top hidden latency and cost sink in agents.

gen_ai.agent.step = 3 recommended

Position in the agent loop — pinpoints where a multi-step plan derailed.

gen_ai.tool.authority = "read_only" recommended

Privilege of the call — flags an agent exceeding its intended scope.

#6 Output guard

guardrail.check · INTERNAL

OpenLLMetry alias: guardrails.validate

Post-generation validation: safety filters, schema/JSON validation, PII redaction, groundedness checks.

Attributes

guardrail.name = "json_schema+pii" required

Which guards ran — a disabled guard is otherwise invisible.

guardrail.passed = false required

Pass/fail outcome; the headline reliability signal for the stage.

guardrail.action = "block" required

pass/block/redact/regenerate — what the user actually saw.

guardrail.violation.type = "pii_email" required

Failure category — drives a violation-type dashboard, not just a count.

guardrail.score = 0.42 recommended

Confidence/groundedness score for tuning the threshold instead of guessing.

guardrail.regenerate.count = 1 recommended

Regeneration loops are a hidden cost and latency multiplier.

guardrail.latency_ms = 180 recommended

Guards on the response path add user-visible latency.

guardrail.redacted.fields = "[email]" recommended

Audit trail for what was scrubbed before the user saw it.

#7 Response / root

gen_ai.workflow · SERVER

OpenLLMetry alias: traceloop.workflow / {service}.request

The root span that ties the whole request together and carries end-to-end, user-facing outcomes.

Attributes

gen_ai.workflow.name = "rag_support_answer" required

Names the pipeline so traces are groupable by product flow, not endpoint.

session.id = "sess_9a1" required

Stitches multi-turn conversations and reproduces a user's whole journey.

gen_ai.response.latency_ms = 2400 required

The number the user feels — the SLO that matters.

gen_ai.workflow.status = "ok" required

End-to-end success/failure independent of any single stage.

user.feedback = "thumbs_down" recommended

The only direct quality label most prod systems get — attach it to the trace.

gen_ai.cost.usd = 0.013 recommended

Rolled-up request cost for per-feature/per-tenant economics.

deployment.version = "2026.05.1" recommended

Correlates a quality/cost shift to a specific release.

tenant.id = "acme" recommended

Per-tenant SLOs, cost, and abuse isolation.

Attribute keys follow the OpenTelemetry GenAI semantic conventions (gen_ai.*) plus OpenLLMetry/Traceloop extensions where the spec is still incubating. Span kind is INTERNAL unless the stage crosses a process/network boundary (CLIENT).

Read: what belongs in a span →

Related tools in this network

Other interactive tools across the network that pair well with this one.