Langfuse Observability Skill
Query Langfuse observability data via REST API to debug agent runs, analyze LLM costs, and inspect prompt versions. This skill complements the Langfuse Prompt MCP (built-in) which handles prompt CRUD — this skill covers everything else.
Prerequisites
Authentication: All API calls require HTTP Basic Auth.
- Username:
LANGFUSE_PUBLIC_KEY(e.g.,pk-lf-...) - Password:
LANGFUSE_SECRET_KEY(e.g.,sk-lf-...)
Base URL: Read from .env:
grep LANGFUSE_BASE_URL .env # e.g., http://localhost:4300Quick connectivity check:
curl -s -u "pk-lf-...:sk-lf-..." "${LANGFUSE_BASE_URL:-http://localhost:4300}/api/public/projects" | jq '.'Self-Hosted vs Cloud API Differences
| Feature | Self-Hosted | Cloud |
|---|---|---|
| Traces (v1) | ✅ | ✅ |
| Observations (v1) | ✅ | ✅ |
| Observations (v2, cursor-based) | ❌ Cloud-only beta | ✅ |
| Metrics (v2, aggregated analytics) | ❌ Limited/unsupported | ✅ |
| Scores | ✅ | ✅ |
| Sessions | ✅ | ✅ |
| Prompts | ✅ | ✅ |
| Datasets | ✅ | ✅ |
| Comments | ✅ | ✅ |
| Annotation Queues | ✅ | ✅ |
| Score Configs | ✅ | ✅ |
Always use v1 endpoints for self-hosted. V2 endpoints return NotImplementedError on local instances.
Core API Endpoints
Setup (run once per session)
# Read credentials from .env
LANGFUSE_BASE_URL=$(grep LANGFUSE_BASE_URL .env | cut -d'"' -f2)
LANGFUSE_PK=$(grep LANGFUSE_PUBLIC_KEY .env | cut -d'"' -f2)
LANGFUSE_SK=$(grep LANGFUSE_SECRET_KEY .env | cut -d'"' -f2)
AUTH="-u ${LANGFUSE_PK}:${LANGFUSE_SK}"
BASE="${LANGFUSE_BASE_URL}/api/public"1. Traces — Agent run overviews
List traces with pagination and filters:
# Recent traces (default: 10 per page)
curl -s $AUTH "$BASE/traces?limit=10" | jq '.data[] | {id, name, timestamp, totalCost, latency, userId}'
# Filter by user, tags, time range
curl -s $AUTH "$BASE/traces?limit=10&userId=<user-id>&fromTimestamp=2026-03-20T00:00:00Z&toTimestamp=2026-03-21T23:59:59Z"
# Single trace detail (includes full input/output/metadata)
curl -s $AUTH "$BASE/traces/<trace-id>" | jq '.'Key fields: name (agent/workflow name), input/output, metadata (agent config, instructions), totalCost, latency, observations (child IDs), scores, sessionId, userId
2. Observations — Spans, Generations, Events
# Observations for a specific trace
curl -s $AUTH "$BASE/observations?traceId=<trace-id>&limit=50" | jq '.data[] | {id, type, name, model, startTime, endTime, latency, calculatedTotalCost, usage}'
# Filter by type (SPAN, GENERATION, EVENT)
curl -s $AUTH "$BASE/observations?traceId=<trace-id>&type=GENERATION&limit=20"
# Single observation detail
curl -s $AUTH "$BASE/observations/<observation-id>" | jq '.'Key fields: type (SPAN/GENERATION/EVENT), name, model, input/output, usage (promptTokens, completionTokens), calculatedTotalCost, latency, parentObservationId, metadata, level (DEFAULT/WARNING/ERROR)
3. Sessions — Conversation threads
# List sessions
curl -s $AUTH "$BASE/sessions?limit=20" | jq '.data[] | {id, createdAt, projectId, environment}'
# Get traces for a session (via trace filter)
curl -s $AUTH "$BASE/traces?sessionId=<session-id>&limit=20" | jq '.data[] | {id, name, timestamp, totalCost}'4. Scores — Evaluations
# List scores
curl -s $AUTH "$BASE/scores?limit=20" | jq '.data[]'
# Score configs (templates)
curl -s $AUTH "$BASE/score-configs?limit=20" | jq '.data[]'5. Projects
curl -s $AUTH "$BASE/projects" | jq '.data[] | {id, name, organization}'6. Datasets & Dataset Items
# List datasets
curl -s $AUTH "$BASE/v2/datasets?limit=20" | jq '.data[]'
# Dataset items
curl -s $AUTH "$BASE/dataset-items?datasetName=<name>&limit=20" | jq '.data[]'7. Comments
# List comments (filter by objectType: trace, observation, session, prompt)
curl -s $AUTH "$BASE/comments?limit=20" | jq '.data[]'Common Investigation Workflows
Workflow A: Debug a failed agent run
- Find the trace: Search traces by time range or agent name
curl -s $AUTH "$BASE/traces?limit=20" | jq '[.data[] | {id, name, timestamp, latency, totalCost, level:.metadata.level}]' - Get trace detail: Inspect input/output for the failed trace
curl -s $AUTH "$BASE/traces/<trace-id>" | jq '.' - Find errors in observations: Look for level=WARNING or level=ERROR
curl -s $AUTH "$BASE/observations?traceId=<trace-id>&limit=50" | jq '[.data[] | select(.level!= "DEFAULT") | {id, type, name, level, statusMessage, startTime}]' - Inspect the failing generation: Get full model input/output
curl -s $AUTH "$BASE/observations/<observation-id>" | jq '{type, name, model, input, output, usage, calculatedTotalCost, latency, statusMessage}'
Workflow B: Analyze costs and latency
- Cost overview: Summarize costs across recent traces
curl -s $AUTH "$BASE/traces?limit=50" | jq '{totalCost: ([.data[].totalCost] | add), avgCost: ([.data[].totalCost] | add / length), avgLatency: ([.data[].latency] | add / length), traceCount:.meta.totalItems}' - Per-model breakdown: Extract model costs from generations
curl -s $AUTH "$BASE/observations?limit=100&type=GENERATION" | jq 'group_by(.model) | map({model:.[0].model, count: length, totalCost: (map(.calculatedTotalCost) | add), avgTokens: (map(.usage.total) | add / length)})'
Workflow C: Trace a conversation session
- List sessions: Find the target session
curl -s $AUTH "$BASE/sessions?limit=20" | jq '.data[]' - Get all traces for a session: Full conversation history
curl -s $AUTH "$BASE/traces?sessionId=<session-id>&limit=50" | jq '[.data[] | {id, name, timestamp, input: (.input[0].content |.[0:100]), output: (.output.text //.output | tostring |.[0:100]), totalCost, latency}]'
Workflow D: Audit prompt versions
Use the built-in Langfuse Prompt MCP tools for prompt CRUD:
langfuse_listPrompts— list all promptslangfuse_getPrompt— get compiled prompt with dependencies resolvedlangfuse_getPromptUnresolved— get raw prompt with dependency tagslangfuse_createTextPrompt/langfuse_createChatPrompt— create new versionslangfuse_updatePromptLabels— manage production/staging labels
Note: The REST API GET /api/public/prompts requires a name parameter. Use MCP tools for listing.
Pagination
All v1 endpoints use page-based pagination:
page(starts at 1),limit(default varies, typically 10)- Response includes
meta.totalItemsandmeta.totalPages
# Page through results
curl -s $AUTH "$BASE/traces?limit=50&page=1" | jq '.meta'
curl -s $AUTH "$BASE/traces?limit=50&page=2" | jq '.meta'v2 Cloud endpoints use cursor-based pagination (not available on self-hosted).
Output Truncation
For large responses, always truncate when scanning:
# Truncate long text fields
curl -s $AUTH "$BASE/traces/<id>" | jq '{id, name, input: (.input | tostring | .[0:300]), output: (.output | tostring | .[0:300])}'
# Select only needed fields
curl -s $AUTH "$BASE/observations?traceId=<id>&limit=50" | jq '.data[] | {id, type, name, model, latency, calculatedTotalCost}'Important Notes
- Data freshness: New data appears within 15-30 seconds of ingestion
- Cost fields:
calculatedTotalCoston observations,totalCoston traces - Latency: In seconds (e.g.,
21.968= ~22 seconds) - Usage: Token counts with
unit: "TOKENS", fields:input,output,total - Observation types:
SPAN(workflow step),GENERATION(LLM call),EVENT(log point) - Metadata fields vary by agent/workflow — inspect raw data to discover available keys
References
- Full API reference: See
REFERENCE.md - OpenAPI spec:
https://cloud.langfuse.com/generated/api/openapi.yml - API docs:
https://api.reference.langfuse.com - Langfuse docs MCP (unauthenticated):
https://langfuse.com/api/mcp