Metadata
Observations (see Langfuse Data Model) can be enriched with metadata to help you better understand your application and to correlate observations in Langfuse.
You can filter by metadata keys in the Langfuse UI and API.
With Python SDK v5 and JS/TS SDK v6 on Langfuse v4.59.0 and later, numbers and booleans keep their type and nested objects become filterable dotted paths, such as a.b. If two keys map to the same dotted path, the first value wins.
Propagated Metadata
Use propagate_attributes() to ensure metadata is automatically applied to all observations within a context. Propagated metadata are key-value pairs. In Python SDK v5 and JS/TS SDK v6, values can be strings, numbers, booleans, lists, or objects. Each value must be 200 characters or fewer as JSON, so a string can have at most 198 characters; longer values are dropped with a warning. Top-level null / None values are dropped with a warning too. In Python SDK v4 and JS/TS SDK v5, use string values of 200 characters or fewer. Use alphanumeric characters for keys.
When using the @observe() decorator:
from langfuse import observe, propagate_attributes
@observe()
def process_data():
# Propagate metadata to all child observations
with propagate_attributes(
metadata={"source": "api", "region": "us-east-1", "user_tier": "premium"}
):
# All nested observations automatically inherit this metadata
result = perform_processing()
return resultWhen creating observations directly:
from langfuse import get_client, propagate_attributes
langfuse = get_client()
with langfuse.start_as_current_observation(as_type="span", name="process-request") as root_span:
# Propagate metadata to all child observations
with propagate_attributes(metadata={"request_id": "req_12345", "region": "us-east-1"}):
# All observations created here automatically have this metadata
with root_span.start_as_current_observation(
as_type="generation",
name="generate-response",
model="gpt-4o"
) as gen:
# This generation automatically has the metadata
passWhen using the context manager:
import { startActiveObservation, propagateAttributes } from "@langfuse/tracing";
await startActiveObservation("context-manager", async (span) => {
span.update({
input: { query: "What is the capital of France?" },
});
// Propagate metadata to all child observations
await propagateAttributes(
{
metadata: { source: "api", region: "us-east-1", userTier: "premium" },
},
async () => {
// All observations created here automatically have this metadata
// ... your logic ...
}
);
});When using the observe wrapper:
import { observe, propagateAttributes } from "@langfuse/tracing";
const processData = observe(
async (data: string) => {
// Propagate metadata to all child observations
return await propagateAttributes(
{ metadata: { source: "api", region: "us-east-1" } },
async () => {
// All nested observations automatically inherit this metadata
const result = await performProcessing(data);
return result;
}
);
},
{ name: "process-data" }
);
const result = await processData("input");See JS/TS SDK docs for more details.
from langfuse import get_client, propagate_attributes
from langfuse.openai import openai
langfuse = get_client()
with langfuse.start_as_current_observation(as_type="span", name="openai-call"):
# Propagate metadata to all observations including OpenAI generation
with propagate_attributes(
metadata={"source": "api", "region": "us-east-1"}
):
completion = openai.chat.completions.create(
name="test-chat",
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "You are a calculator."},
{"role": "user", "content": "1 + 1 = "}
],
temperature=0,
)import OpenAI from "openai";
import { observeOpenAI } from "@langfuse/openai";
import { startActiveObservation, propagateAttributes } from "@langfuse/tracing";
await startActiveObservation("openai-call", async () => {
// Propagate metadata to all observations
await propagateAttributes(
{
metadata: { source: "api", region: "us-east-1" },
},
async () => {
const res = await observeOpenAI(new OpenAI()).chat.completions.create({
messages: [{ role: "system", content: "Tell me a story about a dog." }],
model: "gpt-3.5-turbo",
max_tokens: 300,
});
}
);
});from langfuse import get_client, propagate_attributes
from langfuse.langchain import CallbackHandler
langfuse = get_client()
langfuse_handler = CallbackHandler()
with langfuse.start_as_current_observation(as_type="span", name="langchain-call"):
# Propagate metadata to all child observations
with propagate_attributes(
metadata={"foo": "bar", "baz": "qux"}
):
response = chain.invoke(
{"topic": "cats"},
config={"callbacks": [langfuse_handler]}
)import { startActiveObservation, propagateAttributes } from "@langfuse/tracing";
import { CallbackHandler } from "@langfuse/langchain";
const langfuseHandler = new CallbackHandler();
// Propagate metadata to all child observations
await propagateAttributes(
{
metadata: { key: "value" },
},
async () => {
await chain.invoke(
{ input: "<user_input>" },
{ callbacks: [langfuseHandler] }
);
}
);You can set the metadata via the override configs, see the Flowise Integration docs for more details.
Note on Attribute Propagation
- In Python SDK v5 and JS/TS SDK v6, metadata values can be strings, numbers, booleans, lists, or objects, and each value must be โค200 characters as JSON (a string can have at most 198). Top-level
null/Nonevalues are dropped with a warning. In Python SDK v4 and JS/TS SDK v5, use string values โค200 characters. - Metadata keys: use alphanumeric characters (no whitespace or special characters)
- Call early in your trace to ensure all observations are covered. This way you make sure that all Metrics in Langfuse are accurate.
- Invalid values are dropped with a warning
Non-Propagated Metadata
You can also add metadata to specific observations only:
# Python SDK
from langfuse import get_client
langfuse = get_client()
with langfuse.start_as_current_observation(as_type="span", name="process-request") as root_span:
# Add metadata to this specific observation only
root_span.update(metadata={"stage": "parsing"})
# ... or access span via the current context
langfuse.update_current_span(metadata={"stage": "parsing"})// TypeScript SDK
import {
startActiveObservation,
updateActiveObservation,
} from "@langfuse/tracing";
await startActiveObservation("process-request", async (span) => {
// Add metadata to this specific observation only
span.update({
metadata: { stage: "parsing" },
})
// ... or access span via the current context
updateActiveObservation({
metadata: { stage: "parsing" },
});
});GitHub Discussions
Last updated on