opik — Claude Code skill: what it does, how to install
Reference for Opik SDK 2.x tracing, span types, framework integrations, and prompt library management.
npx skills add comet-ml/opik-skills --skill opik -a claude-codeWhat opik does
This skill supplies reference patterns for the Opik Python and TypeScript SDKs. It defines the only four valid span types (general, llm, tool, guardrail) and provides examples for tracking pipelines, models, and tools.
It covers client wrappers and callbacks for frameworks like OpenAI, Anthropic, LangChain, DSPy, and CrewAI. A key detail is handling LiteLLM: running it under @opik.track requires passing current_span_data in metadata, or LiteLLM creates orphaned traces.
Reading the syntax snippets requires no live Opik connection. When an Opik MCP server is available, the skill outlines project metric inspections and OQL filter grammar for traces and spans.
What it helps with
- select valid span types for agent and tool tracking
- instrument Python and TypeScript code with Opik SDK 2.x
- prevent orphaned LiteLLM spans when using decorators
- track multi-turn conversations using thread identifiers
- write OQL filter queries for error-prone or slow traces
Example prompts for the agent
- Show how to wrap an OpenAI client with Opik tracing in Python.
- How do I link multi-turn chat interactions to a thread_id in Opik?
- Write an OQL query to filter traces with errors taking more than 5000 ms.
How to install opik
1Skills CLI (Vercel)
npx skills add comet-ml/opik-skills --skill opik -a claude-code2Manually: put the files in place
~/.claude/skills/opik/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/opik/
1Skills CLI (Vercel)
npx skills add comet-ml/opik-skills --skill opik -a codex2Manually: put the files in place
.agents/skills/opik/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add comet-ml/opik-skills --skill opik -a cursor2Manually: put the files in place
.cursor/skills/opik/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install comet-ml/opik-skills opik2Manually: put the files in place
.github/skills/opik/SKILL.md1Skills CLI (Vercel)
npx skills add comet-ml/opik-skills --skill opik -a gemini-cli2Platform CLI
gemini skills install https://github.com/comet-ml/opik-skills --path skills/opikManually: put the files in place
.devin/skills/opik/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add comet-ml/opik-skills --skill opik -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about opik
How do I install opik in Claude Code?
Run npx skills add comet-ml/opik-skills --skill opik -a claude-code. The skill file will be placed in ~/.claude/skills/opik/SKILL.md.
What does the opik skill do?
It provides an API reference for the Opik LLM observability SDK. It assists agents in drafting correct trace code, picking span types, and configuring framework integrations.
Does reading this skill require an Opik API key or server?
No connection to Opik is needed to read the reference snippets. A server connection or MCP server is only needed when listing live project metrics or searching traces.
Source text
SKILL.md · Apache-2.0
---
name: opik
description: Reference for the Opik SDK — tracing, span types, framework integrations, threads, and the prompt library (Python, TypeScript, REST). Use for "what span types exist", "how do I flush", "track_openai", "add OpikTracer", "version a prompt". To instrument a repo end to end, use the `opik-instrument` skill.
compatibility: Tested with Claude Code; works with any Agent Skills-compatible host (Cursor, VS Code Copilot, Codex). A reference — needs no Opik connection to read; the snippets assume the `opik` Python or TypeScript SDK 2.x. The task-shaped skills (opik-instrument, opik-diagnose, opik-explain, opik-test, opik-compare, opik-evaluate, opik-online-eval, opik-optimize, opik-verify) read this skill's references and expect it installed beside them.
allowed-tools:
- Read
- Grep
- Glob
metadata:
last_updated: "2026-09-17"
source_commit: "2.0.0"
---
# 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
| Type | Use for |
|------|---------|
| `general` | orchestration, agent entry points |
| `llm` | model calls |
| `tool` | tools, retrieval, API / DB calls |
| `guardrail` | safety / validation checks |
Do NOT use `retrieval` or any other value.
## Python — tracing
```python
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
```typescript
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.
```python
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.
```python
@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.
```python
@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:
```python
client.search_traces(project_name="<project>", filter_string="error_info is_not_empty")
```
## Anti-patterns
| Anti-pattern | Fix |
|--------------|-----|
| span type `retrieval` / custom | use `tool` (or `general`) |
| `get_prompt` outside `@opik.track` | fetch inside — else no trace link |
| deprecated `opik.Prompt` / `opik.Config` | use `client.get_prompt` / config file |
| `litellm` without `current_span_data` | pass it — else orphaned traces |
| no flush in scripts | `opik.flush_tracker()` / `await client.flush()` |
## References
| Topic | File |
|-------|------|
| Python SDK (async, distributed, context) | `references/tracing-python.md` |
| TypeScript SDK | `references/tracing-typescript.md` |
| REST API | `references/tracing-rest-api.md` |
| All integrations | `references/integrations.md` |
| Core concepts (traces, spans, threads) | `references/observability.md` |
| Best practices (lifecycle, monitoring, anti-patterns) | `references/best-practices.md` |
| Agent architecture, reliability, security | `references/agent-patterns.md` |
| Production monitoring, alerts, guardrails | `references/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.
© comet-ml · Apache-2.0 · comet-ml/opik-skills