mcpField
O
opik

opik

github.com/comet-mlDevelopment8537 installsUpdated 5w ago
Repository

About opik

opik is an SDK and LLM observability reference skill for developers adding traces, managing prompt versions, and evaluating systems. It also explains querying project metrics and traces through MCP.

Key features

  1. 01Create traces and spans with Python and TypeScript
  2. 02Capture model-call details through integrations
  3. 03Group multi-turn traces by conversation thread
  4. 04Manage prompt versions and link them to traces
  5. 05Search traces, spans, and threads with OQL
  6. 06Inspect project metrics and recent activity

Use cases

  1. 01Trace agent runs and tool calls
  2. 02Review project error rates, duration, and cost
  3. 03Filter problematic traces and break down metrics by model
  4. 04Group multiple conversation turns in one thread

MCP support

The reference describes connecting to MCP to read project overviews and use list for traces, spans, threads, and project metrics. The schema tool provides field and filter references.

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/comet-ml/opik-skills --skill opik

After installing, type/opikin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
agent-patterns.md
best-practices.md
evaluation-datasets.md
evaluation-test-suites.md
integrations.md
observability.md
production.md
tracing-python.md
tracing-rest-api.md
tracing-typescript.md

Details

From the project README

Opik SDK Reference

Opik is an open-source LLM observability platform. This skill is a reference for the SDK. To instrument a codebase step by step (detect frameworks, add config, emit and verify a trace), use the task-shaped opik-instrument skill.

Core concepts

A trace is one execution path (one request → one response). Spans are the operations inside it and form a hierarchy.

Span types — the ONLY valid values
TypeUse for
generalorchestration, agent entry points
llmmodel calls
tooltools, retrieval, API / DB calls
guardrailsafety / validation checks

Do NOT use retrieval or any other value.

Python — tracing

import opik

@opik.track(name="agent", type="general")
def agent(query: str) -> str:
    return generate(retrieve(query))

@opik.track(type="tool")
def retrieve(query): ...

@opik.track(type="llm")
def generate(ctx): ...

opik.flush_tracker()   # required in scripts

TypeScript — tracing

import { Opik } from "opik";
const client = new Opik({ projectName: "my-project" });

const trace = client.trace({ name: "agent", input: { query } });
const span = trace.span({ name: "llm-call", type: "llm" });
span.end({ output });
trace.end({ output });
await client.flush();

Framework integrations

Prefer an integration over manual @opik.track — integrations capture tokens, model, and cost automatically. Patterns (full list in references/integrations.md):

  • wrap-the-client — track_openai(OpenAI()), track_anthropic(...)
  • global-enable — track_crewai(crew=crew)
  • callback — dspy.configure(callbacks=[OpikCallback()])
  • tracer — OpikTracer() for LangChain / LangGraph / LlamaIndex
  • agent-specific — track_adk_agent_recursive(agent, OpikTracer())
LiteLLM inside @opik.track (common trap)

If code uses litellm and you add @opik.track, pass current_span_data via metadata on every completion call — otherwise OpikLogger emits orphaned top-level traces instead of nesting under your span.

from opik.opik_context import get_current_span_data

@opik.track
def call_llm(messages):
    return litellm.completion(
        model="gpt-4o", messages=messages,
        metadata={"opik": {"current_span_data": get_current_span_data()}},
    )

Threads (conversations)

Group turns with thread_id — one turn = one trace, shared thread_id = one thread. Use for chat / multi-turn; skip for single-shot.

@opik.track(entrypoint=True)
def handle(session_id: str, message: str) -> str:
    opik.update_current_trace(thread_id=session_id)
    return reply(message)

Prompt library

Version prompts with client.get_prompt / create_prompt (chat variants: get_chat_prompt / create_chat_prompt). Store model + temperature in the prompt metadata so they version with the text. Call get_prompt inside a @opik.track function so the version links to the trace.

@opik.track(entrypoint=True)
def run(question: str) -> str:
    p = client.get_prompt(name="system") or client.create_prompt(
        name="system",
        prompt="You help with {{product}}.",
        metadata={"model": "gpt-4o", "temperature": 0.7},
    )
    return llm(p.format(product="Opik"), model=p.metadata["model"])

How a project is doing

With the MCP connected, start at the project, not at its traces:

read("project", "<project name or id>")

One call returns the last 7 days against the 7 before — trace count, error rate, average duration, total cost, SDK traffic only, which is what the Logs page's four cards show — plus the score names and usage keys the project actually records, and the freshest experiment, dataset, prompt version and optimization run in it. since/until pick another window; since="30d" is what the UI opens on. A rate or an average over a window with no traces comes back null rather than 0, because a rate over no samples is undefined and "0% errors" is advice someone may act on.

Then attribute the change rather than restating it:

list("project_metric", project_name="<project>", metric_type="trace_cost")
list("project_metric", project_name="<project>", metric_type="span_count",
     breakdown="model", since="30d")

Rows are time buckets, not records — interval is hourly/daily/weekly/ total, and page/size/sort do not apply. schema("list.project_metric") is the metric list, what each is about, and which groupings each accepts; seven of them accept none. The score names the overview returned are the ones worth filtering on, and list("score_name", project_name=…) has the rest.

Searching traces

One filter grammar, OQL, serves both the hosted MCP's list tool and the SDK's search_traces / search_spans / search_threads:

<field>[.<key>] <op> <value> [AND ...]
ops: = != > >= < <= contains not_contains starts_with ends_with is_empty is_not_empty in not_in

Strings in double quotes, numbers bare, duration in milliseconds, dates as ISO-8601 instants with a timezone ("2026-09-08T10:00:00Z"). Scores and dictionaries take a key: feedback_scores.accuracy < 0.5, metadata.environment = "prod". AND is the only connector.

error_info is_not_empty AND duration > 5000
type = "llm" AND usage.total_tokens > 10000            # spans
feedback_scores.hallucination > 0.5 AND start_time >= "2026-09-08T00:00:00Z"

With the MCP connected, prefer list — it also sorts (sort="duration desc"), windows (since="1h", "7d"), and searches free text (search="order-42"):

list(entity_type="trace", project_name="<project>", since="1h",
     filters="error_info is_not_empty", sort="duration desc")

Trace, span and thread lists add source = "sdk" unless you name source, so evaluator, playground and experiment traces stay out of the way. A rejected filter comes back with what fixes it; schema("list.trace") (or list.span, list.thread, list.experiment) is the full field and operator reference.

Without the MCP, the same string goes to the SDK:

client.search_traces(project_name="<project>", filter_string="error_info is_not_empty")

Anti-patterns

Anti-patternFix
span type retrieval / customuse tool (or general)
get_prompt outside @opik.trackfetch inside — else no trace link
deprecated opik.Prompt / opik.Configuse client.get_prompt / config file
litellm without current_span_datapass it — else orphaned traces
no flush in scriptsopik.flush_tracker() / await client.flush()

References

TopicFile
Python SDK (async, distributed, context)references/tracing-python.md
TypeScript SDKreferences/tracing-typescript.md
REST APIreferences/tracing-rest-api.md
All integrationsreferences/integrations.md
Core concepts (traces, spans, threads)references/observability.md
Best practices (lifecycle, monitoring, anti-patterns)references/best-practices.md
Agent architecture, reliability, securityreferences/agent-patterns.md
Production monitoring, alerts, guardrailsreferences/production.md
Evaluation datasets & test suites (reference)references/evaluation-datasets.md, references/evaluation-test-suites.md

To build and run an evaluation, use the opik-evaluate skill. For repo instrumentation and config, use the opik-instrument skill.

Comments

Markdown supported