Langfuse
Langfuse 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 and token usage, plus conversation flows.
InstallationDirect link to Installation
- npm
- pnpm
- Yarn
- Bun
npm install @mastra/langfuse@latest
pnpm add @mastra/langfuse@latest
yarn add @mastra/langfuse@latest
bun add @mastra/langfuse@latest
ConfigurationDirect link to Configuration
PrerequisitesDirect link to Prerequisites
- Langfuse Account: Sign up at cloud.langfuse.com or deploy self-hosted
- API Keys: Create public/secret key pair in Langfuse Settings → API Keys
- Environment Variables: Set your credentials
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 SetupDirect link to Zero-Config Setup
With environment variables set, use the exporter with no configuration:
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 ConfigurationDirect link to Explicit Configuration
You can also pass credentials directly (takes precedence over environment variables):
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 optionsDirect link to Configuration options
Realtime vs Batch ModeDirect link to Realtime vs Batch Mode
The Langfuse exporter supports two modes for sending traces:
Realtime Mode (Development)Direct link to Realtime Mode (Development)
Traces appear immediately in Langfuse dashboard, ideal for debugging:
new LangfuseExporter({
publicKey: process.env.LANGFUSE_PUBLIC_KEY!,
secretKey: process.env.LANGFUSE_SECRET_KEY!,
realtime: true, // Flush after each event
})
Batch Mode (Production)Direct link to Batch Mode (Production)
Better performance with automatic batching:
new LangfuseExporter({
publicKey: process.env.LANGFUSE_PUBLIC_KEY!,
secretKey: process.env.LANGFUSE_SECRET_KEY!,
realtime: false, // Default - batch traces
})
Batch Tuning for High-Volume TracesDirect link to 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:
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 rather than configuring the exporter:
import { SpanType } from '@mastra/core/observability'
new Observability({
configs: {
langfuse: {
serviceName: 'my-service',
exporters: [new LangfuseExporter()],
excludeSpanTypes: [SpanType.MODEL_CHUNK],
},
},
})
Complete ConfigurationDirect link to Complete Configuration
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 agentDirect link to 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 idlangfuse.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:
agentIdequals the agent id.
The trace name dropdown in Langfuse evaluator filters lists every distinct value seen, so each agent is shown 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.
Custom trace metadataDirect link to Custom trace metadata
Langfuse filters and groups traces by top-level metadata only. Nested metadata keys can't be used for filtering or grouping.
To add your own top-level metadata, set keys under langfuse in your span metadata. The exporter forwards each key to langfuse.trace.metadata.<key>, where it becomes filterable in Langfuse:
const tracingOptions = {
metadata: {
langfuse: {
customerId: 'cust_123',
tier: 'enterprise',
},
},
}
This example produces langfuse.trace.metadata.customerId and langfuse.trace.metadata.tier.
Metadata on the root span is also forwarded. Mastra sets runId and resourceId on every agent and workflow root span, and you can add your own keys through tracingOptions.metadata. The exporter forwards each of these root span keys to langfuse.trace.metadata.<key>. Keys that map to a dedicated Langfuse field (userId, sessionId, threadId, traceName, and version) are not duplicated as trace metadata. Other metadata on child spans stays on the observation. Dedicated fields such as session IDs follow their own mapping rules.
Notes:
- The reserved
promptkey is used for prompt linking and isn't forwarded as trace metadata. - The reserved identity keys
agentId,agentName,workflowId, andworkflowNameare set from the root span and take precedence over custom values with the same name. - Keys under
langfusetake precedence over root span metadata with the same name. - Values are sent as strings, because Langfuse maps trace metadata attributes as strings. Numbers, booleans, and objects are serialized with JSON. Langfuse Cloud restores them to their original types on ingestion.
Conversation sessionsDirect link to Conversation sessions
The exporter maps span metadata to Langfuse sessions using sessionId, or threadId when sessionId is absent or null. An explicit empty sessionId suppresses this fallback and sends no session ID.
For Observational Memory, the Langfuse exporter keeps observer and reflector spans in the caller's session, even when child spans arrive before their parents. An explicit sessionId, including an empty string, takes precedence. Otherwise, the exporter uses the original caller thread carried by Observational Memory before falling back to the span's own threadId. Observational Memory captures that caller identity from the caller span's non-empty threadId, or the original request's thread ID. Nested observation preserves the outer caller identity.
This thread-to-session fallback is specific to Langfuse. Observational Memory doesn't synthesize generic sessionId metadata from a thread ID for other exporters.
Internal observer and reflector execution threads remain separate. Multi-thread observation uses the invoking caller's session, not the first thread in the batch. This session behavior applies regardless of the bufferOnIdle setting and doesn't change buffering or span parentage.
Prompt linkingDirect link to Prompt linking
You can link LLM generations to prompts stored in Langfuse Prompt Management. It enables version tracking and metrics for your prompts.
Using the Helper (Recommended)Direct link to Using the Helper (Recommended)
Use withLangfusePrompt with buildTracingOptions for the cleanest API:
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({
id: 'support-agent',
name: 'support-agent',
instructions: prompt.compile(), // Use the prompt text from Langfuse
model: 'openai/gpt-5.6-sol',
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 FieldsDirect link to Manual Fields
You can also pass manual fields if you're not using the Langfuse SDK:
const tracingOptions = buildTracingOptions(withLangfusePrompt({ name: 'my-prompt', version: 1 }))
Prompt Object FieldsDirect link to 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.
Import existing traces into Mastra PlatformDirect link to Import existing traces into Mastra Platform
The Mastra CLI can import historical trace observations from Langfuse Cloud or a self-hosted Langfuse v4 or later instance. This is separate from configuring the exporter on this page. See Import existing traces for credentials, dry runs, resume, verification, and current limits.