Send completed LLM traces, generations, and scores from Convex actions to Langfuse over OpenTelemetry, with reactive local queries of all logged data.
npm install convex-langfuseconvex-langfuse bridges Convex actions and Langfuse observability by exporting completed LLM calls as OpenTelemetry spans via Langfuse's OTLP/HTTP endpoint, bypassing the deprecated batch ingestion API. Because Convex actions are stateless and short-lived, the component accepts already-finished input/output/token data rather than managing open spans. Every trace, observation, and score is also written to Convex tables, enabling reactive queries over your LLM history without additional Langfuse API calls.
convex-langfuse provides a Langfuse client that works inside Convex actions. Call logGeneration(ctx, { name, model, input, output, inputTokens, outputTokens }) after your LLM call completes, and the component exports a finished OpenTelemetry span to Langfuse and mirrors the data into Convex tables. No streaming or long-lived spans are required.
Pass inputTokens, outputTokens, and model to logGeneration() in convex-langfuse. Langfuse computes cost from those values using its pricing table for the named model. The same fields are stored in the local observations table and are queryable reactively via listObservations().
convex-langfuse exposes recordScore(ctx, { traceId, name, value, comment }) as a Convex action. Pass the traceId returned from logGeneration() along with a numeric value such as 1 for thumbs up or 0 for thumbs down. The score is sent to Langfuse's Scores REST endpoint and stored locally for reactive querying via listScores().
convex-langfuse supports multi-step traces by reusing a traceId across calls. The first logGeneration() or logSpan() call returns a traceId. Pass that same traceId into subsequent logSpan() or logGeneration() calls to attach retrieval steps, tool calls, or additional generations as observations under the same Langfuse trace.
Yes. convex-langfuse is designed specifically for Convex actions, which are short stateless functions. Instead of opening and closing spans around an async process, you call logGeneration() or logSpan() once with the already-finished input, output, and timing. The component constructs and exports a completed OpenTelemetry span in a single call.
convex-langfuse sends data to Langfuse's OTLP/HTTP endpoint using Langfuse's documented span attribute conventions. It does not use the older /api/public/ingestion batch endpoint, which is deprecated and scheduled for sunset on Langfuse Cloud on November 16, 2026. The component constructs minimal OTLP/HTTP JSON payloads over fetch with no OpenTelemetry SDK dependency.
Yes. convex-langfuse mirrors every trace, observation, and score into Convex tables as they are logged. You can use getTrace(), listObservations(), listScores(), listTracesByUser(), listTracesBySession(), listRecentTraces(), and getStats() as reactive Convex queries, without making any calls to the Langfuse API.
No. convex-langfuse talks directly to Langfuse's OTLP/HTTP and Scores REST endpoints using fetch. It does not depend on the Langfuse SDK or any OpenTelemetry SDK package. This keeps the component dependency-free but means it only supports the attributes documented in its README.
Set the baseUrl option when initializing the Langfuse client in convex-langfuse. The default baseUrl targets the EU Langfuse Cloud region. For US, JP, HIPAA, or self-hosted deployments, pass the correct base URL for your project. Also confirm that your Convex deployment can reach the Langfuse OTLP endpoint over HTTPS, as firewall rules can silently block exports.