Skip to main content
The SDK can record every session’s live events as OpenTelemetry spans. You turn it on once, on the client, and it works for local and cloud sessions with no CLI flag. The SDK only creates spans through @opentelemetry/api. Your app sets up the tracer provider and exporter, so you can send traces to Langfuse or any other OpenTelemetry backend.
Cloud sessions currently report turns and tool calls but not per-request token usage or cost, so their traces have no generation spans. Local sessions report both.

Install

@opentelemetry/api is an optional peer dependency of the SDK. For Langfuse, also install the OpenTelemetry trace SDK and Langfuse’s span processor:

Trace every session

Pass tracing: traceSessions(...) when you create the client. createDevin, LocalDevin.start, LocalDevin.connect and CloudDevin.connect all accept it.
What gets traced:
  • Every session the client opens: createSession, loadSession, attach and launchSession.
  • Every prompt: send, run, stream, streamUpdates and postMessage, including images and other content blocks. The prompt is recorded as the turn’s input.
  • Cloud messages from other clients: a message sent from the Devin web app, Slack or another SDK process is traced as its own turn. Your own prompts are not counted twice.
  • Attach and reload: history replayed by loadSession or attach is not exported again. A turn that is already running when you attach is traced from then on.
Tracing for a session ends when the session is released, the client closes or the connection drops, and any unfinished turn is ended then. A session’s tracing option refines the client’s: metadata is merged, tags are added, and name, userId and sessionId replace the client’s values. Pass tracing: false to leave one session untraced. If your app already registers a global provider (for example with @opentelemetry/sdk-node), leave out tracer and spans use the global provider. Pass parent to nest turns under an existing span, such as your harness’s own request span. Set recordContent: false to keep timing, token usage, cost, model and tool names but leave out prompt, reply and tool text.

Trace one session

traceSession traces a single session you already hold, without a client-level option. It only sees the session’s incoming events, so record each prompt yourself before you send it:
It takes the same options as traceSessions.

What a trace contains

Each turn is its own trace unless it has a parent span. Langfuse groups the turns by session id, which defaults to the Devin session’s id, so a session reloaded in a new process shows up in the same Langfuse session. The last generation of a turn also carries the turn’s request id, time to first token, and ACU cost when the agent reports it. Set usdPerAcu to also record that cost in dollars. Spans also set gen_ai.* attributes for backends other than Langfuse. Turns that stop on error, quota_exhausted, auth_required or content_filter are marked as errors. A provider refusal ends the turn with content_filter and keeps any partial output; the session can take the next prompt. Failed tool calls are errors, and rejected or cancelled ones are warnings.

Running it in production

  • The process running the session needs the Langfuse endpoint, the public and secret keys, and network access to Langfuse.
  • Batching, retries and export errors are handled by your span processor. A Langfuse outage never throws into the session.
  • If the session’s event stream fails, the open turn is marked stream_error, and the session reports the failure to your code as it normally would.
  • Cost fields are only set when the agent reports them. If they are empty, compute cost from the token counts.