Skip to main content

Overview

If your agent is already instrumented with Langfuse, calado can consume the traces Langfuse is already collecting. You do not re-instrument your app and you do not add the calado SDK. Langfuse posts each finished trace to calado, and the format: "langfuse" adapter normalizes it into the canonical conversation and per-step structure the rest of calado uses. Use this page if your agent runs on Langfuse. For provider clients with no tracer, see the Node.js SDK or Direct API. For LangChain or LangGraph agents, see LangChain and LangSmith. There are two ways in:

Webhook

Langfuse’s built-in webhook posts every finished trace to calado in real time. Zero code in your runtime. Recommended.

Forwarder script

A small script paginates Langfuse traces on a cursor and POSTs each batch. Use it for backfill or where webhooks are not an option.
Both paths hit POST /api/ingest with the same payload shape. Pick one.

Webhook setup

LangFuse only sends a webhook when a trigger fires. Pointing the URL at calado does nothing on its own. This is the step customers most often miss.
1

Get your calado API key

In the calado dashboard, open your agent’s Settings page and create an API key. It is prefixed with cl_. You paste it into Langfuse in the next step.
2

Create the webhook

In Langfuse, open your project and go to Settings → Webhooks → Create webhook.
  • URLhttps://app.calado.ai/api/ingest
  • HTTP headers — add Authorization: Bearer cl_<your_calado_api_key>
  • Body format — JSON, using Langfuse’s full trace payload option.
3

Add a trigger

Create a trigger on Trace finished. Without a trigger the webhook stays silent. Optionally add filters (project, environment tag, release) so noisy dev traces are not forwarded.
4

Send a test trace

Run your agent once. Langfuse’s webhook delivery log should show a 202, and the conversation appears in calado within a few seconds.

Payload envelope

calado expects the trace wrapped in an envelope:
{
  "format": "langfuse",
  "conversations": [
    { "trace": { ... }, "observations": [ ... ] }
  ]
}
If your Langfuse webhook sends {trace, observations} directly, without the outer format and conversations envelope, put a small relay in front of calado that wraps the body. A single Cloudflare Worker or Vercel function is enough. The forwarder script below also does this and can run as the relay.

Verifying it works

In calado, open Agents → (your agent) → Conversations. A forwarded trace shows up as a conversation whose externalId is the Langfuse trace.id. Any system prompt or tool schema Langfuse captured appears under Agent definitions. Raw conversations appear immediately. Analysis does not start automatically — click Run Analysis on the agent page when you are ready to classify.

Multi-agent traces

Langfuse traces with nested observations (an orchestrator and its sub-agents, linked via parentObservationId) map cleanly onto calado’s step model. Each sub-agent span becomes a step on one conversation, and the dashboard renders the orchestrator and its sub-agents as a tree. For aggregation to work, every step of one trace has to share a session id. The adapter uses trace.sessionId when Langfuse has one, and falls back to trace.id when it does not, so multi-agent traces collapse into a single conversation row either way. You do not need to set anything.

What gets captured

calado fieldLangfuse source
conversation.externalIdtrace.id
conversation.sessionIdtrace.sessionId, falling back to trace.id
conversation.messagesGENERATION observation input and output messages
Step name and hierarchyObservation name, id, parentObservationId
System promptSystem-role messages in a GENERATION input
Tool schemasGENERATION input.tools and modelParameters.tools
Per-step inline definitionA child observation’s system-role input message, attached as that step’s inlineDefinition so the sub-agent is analyzed against its own prompt
Tool callsSPAN observations with tool execution
Trace eventsAll observations, with timestamps and durations
Token usage and modelGENERATION usage and model metadata
Tags, release, version, user idconversation.metadata
Anthropic-shaped and OpenAI-shaped message content are both normalized. Multimodal blocks (images, audio) pass through untouched. A trace with no LLM activity is stored but marked as skipped for classification, so empty traces do not create noise in the dashboard.

Forwarder script

Use the forwarder for backfills, or where the webhook route is not viable. It polls the Langfuse API on a cursor and POSTs each batch to calado.
npm install langfuse
export LANGFUSE_PUBLIC_KEY=pk_lf_...
export LANGFUSE_SECRET_KEY=sk_lf_...
export LANGFUSE_BASE_URL=https://cloud.langfuse.com   # or your self-hosted URL
export CALADO_API_KEY=cl_...
export CALADO_BASE_URL=https://app.calado.ai

npx tsx forward.ts
The script keeps a local cursor file (.langfuse-cursor.json) so re-runs forward only new traces. The first run backfills everything; later runs are incremental. The full script is in the examples/langfuse-forwarder/ directory of the calado repo, ready to copy.

Caps

LimitValue
Request body size5 MB
Observations per trace950
Conversations per request1,000
Message content1 MB
If a single trace exceeds the observation cap, calado returns a structured 400 too_many_child_runs naming the trace. The practical limit is usually the 5 MB body cap, which a verbose trace reaches well before 950 observations. If you hit either, reduce trace verbosity (drop noisy EVENT observations) or split long-running work into shorter sessions.

Security

The webhook setup puts your calado API key into Langfuse’s webhook configuration UI, as a header value. Anyone with access to your Langfuse project settings can read it. That is a slightly wider exposure surface than the direct-SDK path, where the key only ever lives in your runtime environment.
Treat the webhook key like any credential stored in a third-party tool. Create a dedicated calado key for the Langfuse webhook so you can rotate just that one, and rotate it whenever someone with Langfuse settings access leaves your team. calado keys are one key per agent, so a leaked key can only POST to that single agent’s stream.
Webhook-scoped sub-keys, where a leaked webhook key cannot be used for anything else, are on the calado roadmap. Until then, the rotation discipline above is the mitigation.

Troubleshooting

The webhook returns 400 too_many_child_runs. One trace exceeded the per-trace observation cap. Reduce verbosity or split the trace into shorter sessions. The webhook returns 401. The bearer token was rejected. Re-paste the key into the Langfuse webhook header. The usual cause is a stray space or a missing Bearer prefix. No webhook activity at all. The trigger is not configured. A webhook URL with no trigger never fires. See Webhook setup, step 3.

Next: redacting sensitive data

Strip PII before traces leave your infrastructure.