# Langfuse exporter [Langfuse](https://langfuse.com/) is an open-source observability platform specifically designed for LLM applications. The Langfuse exporter sends your traces to Langfuse, providing detailed insights into model performance, token usage, and conversation flows. ## Installation **npm**: ```bash npm install @mastra/langfuse@latest ``` **pnpm**: ```bash pnpm add @mastra/langfuse@latest ``` **Yarn**: ```bash yarn add @mastra/langfuse@latest ``` **Bun**: ```bash bun add @mastra/langfuse@latest ``` ## Configuration ### Prerequisites 1. **Langfuse Account**: Sign up at [cloud.langfuse.com](https://cloud.langfuse.com) or deploy self-hosted 2. **API Keys**: Create public/secret key pair in Langfuse Settings → API Keys 3. **Environment Variables**: Set your credentials ```bash LANGFUSE_PUBLIC_KEY=pk-lf-xxxxxxxxxxxx LANGFUSE_SECRET_KEY=sk-lf-xxxxxxxxxxxx LANGFUSE_BASE_URL=https://cloud.langfuse.com # Or your self-hosted URL ``` ### Zero-Config Setup With environment variables set, use the exporter with no configuration: ```typescript import { Mastra } from '@mastra/core' import { Observability } from '@mastra/observability' import { LangfuseExporter } from '@mastra/langfuse' export const mastra = new Mastra({ observability: new Observability({ configs: { langfuse: { serviceName: 'my-service', exporters: [new LangfuseExporter()], }, }, }), }) ``` ### Explicit Configuration You can also pass credentials directly (takes precedence over environment variables): ```typescript import { Mastra } from '@mastra/core' import { Observability } from '@mastra/observability' import { LangfuseExporter } from '@mastra/langfuse' export const mastra = new Mastra({ observability: new Observability({ configs: { langfuse: { serviceName: 'my-service', exporters: [ new LangfuseExporter({ publicKey: process.env.LANGFUSE_PUBLIC_KEY!, secretKey: process.env.LANGFUSE_SECRET_KEY!, baseUrl: process.env.LANGFUSE_BASE_URL, environment: process.env.NODE_ENV, release: process.env.GIT_COMMIT, }), ], }, }, }), }) ``` ## Configuration options ### Realtime vs Batch Mode The Langfuse exporter supports two modes for sending traces: #### Realtime Mode (Development) Traces appear immediately in Langfuse dashboard, ideal for debugging: ```typescript new LangfuseExporter({ publicKey: process.env.LANGFUSE_PUBLIC_KEY!, secretKey: process.env.LANGFUSE_SECRET_KEY!, realtime: true, // Flush after each event }) ``` #### Batch Mode (Production) Better performance with automatic batching: ```typescript new LangfuseExporter({ publicKey: process.env.LANGFUSE_PUBLIC_KEY!, secretKey: process.env.LANGFUSE_SECRET_KEY!, realtime: false, // Default - batch traces }) ``` #### Batch Tuning for High-Volume Traces For self-hosted Langfuse deployments or streamed runs that produce many spans per second, you can tune the OTEL batch size and flush interval to reduce request pressure on the Langfuse ingestion endpoint: ```typescript new LangfuseExporter({ publicKey: process.env.LANGFUSE_PUBLIC_KEY!, secretKey: process.env.LANGFUSE_SECRET_KEY!, flushAt: 500, // Maximum spans per OTEL export batch flushInterval: 20, // Maximum seconds between flushes }) ``` To suppress high-volume span types entirely (for example `MODEL_CHUNK` spans from streamed responses), use the observability-level [`excludeSpanTypes` option](https://mastra.ai/reference/observability/tracing/span-filtering) rather than configuring the exporter: ```typescript import { SpanType } from '@mastra/core/observability' new Observability({ configs: { langfuse: { serviceName: 'my-service', exporters: [new LangfuseExporter()], excludeSpanTypes: [SpanType.MODEL_CHUNK], }, }, }) ``` ### Complete Configuration ```typescript new LangfuseExporter({ // Required credentials publicKey: process.env.LANGFUSE_PUBLIC_KEY!, secretKey: process.env.LANGFUSE_SECRET_KEY!, // Optional settings baseUrl: process.env.LANGFUSE_BASE_URL, // Default: https://cloud.langfuse.com realtime: process.env.NODE_ENV === 'development', // Dynamic mode selection flushAt: 500, // Maximum spans per OTEL export batch flushInterval: 20, // Maximum seconds between flushes logLevel: 'info', // Diagnostic logging: debug | info | warn | error // Langfuse-specific settings environment: process.env.NODE_ENV, // Shows in Langfuse UI for filtering release: process.env.GIT_COMMIT, // Git commit hash for version tracking }) ``` ## Scoping evaluators per agent Langfuse evaluators (such as LLM-as-a-Judge) can be filtered to run only against specific traces. The Mastra Langfuse exporter automatically scopes each trace to the agent or workflow that started it, so trace-level filters resolve to the right runs. For every trace whose root span is an `AGENT_RUN`, the exporter sets: - `langfuse.trace.name`: the agent name (or id, when no name is set) - `langfuse.trace.metadata.agentId`: the agent id - `langfuse.trace.metadata.agentName`: the agent name The same applies to `WORKFLOW_RUN` root spans, which set `langfuse.trace.metadata.workflowId` and `langfuse.trace.metadata.workflowName`. To scope an evaluator to a specific agent, configure either filter in Langfuse: - **Trace name**: equals the agent name (for example, `weather-agent`). - **Metadata**: `agentId` equals the agent id. The trace name dropdown in Langfuse evaluator filters lists every distinct value seen, so each agent appears as its own entry once it has produced at least one trace. If you set a custom `traceName` via `mastra.metadata.traceName`, your value takes precedence over the default agent name. ## Prompt linking You can link LLM generations to prompts stored in [Langfuse Prompt Management](https://langfuse.com/docs/prompt-management). This enables version tracking and metrics for your prompts. ### Using the Helper (Recommended) Use `withLangfusePrompt` with `buildTracingOptions` for the cleanest API: ```typescript import { Agent } from '@mastra/core/agent' import { buildTracingOptions } from '@mastra/observability' import { LangfuseExporter, withLangfusePrompt } from '@mastra/langfuse' const exporter = new LangfuseExporter() // Fetch the prompt from Langfuse Prompt Management via the client const prompt = await exporter.client.prompt.get('customer-support', { type: 'text' }) export const supportAgent = new Agent({ name: 'support-agent', instructions: prompt.compile(), // Use the prompt text from Langfuse model: 'openai/gpt-5.5', defaultGenerateOptions: { tracingOptions: buildTracingOptions( withLangfusePrompt({ name: prompt.name, version: prompt.version }), ), }, }) ``` The `withLangfusePrompt` helper accepts `name` and `version` fields for prompt linking. Langfuse v5 requires both fields. ### Manual Fields You can also pass manual fields if you're not using the Langfuse SDK: ```typescript const tracingOptions = buildTracingOptions(withLangfusePrompt({ name: 'my-prompt', version: 1 })) ``` ### Prompt Object Fields The prompt object requires both `name` and `version`: | Field | Type | Description | | --------- | ------ | --------------------------- | | `name` | string | The prompt name in Langfuse | | `version` | number | The prompt version number | When set on a `MODEL_GENERATION` span, the Langfuse exporter automatically links the generation to the corresponding prompt. ## Related - [Tracing Overview](https://mastra.ai/docs/observability/tracing/overview) - [Langfuse Documentation](https://langfuse.com/docs) - [Langfuse Prompt Management](https://langfuse.com/docs/prompt-management)