If you copy a Langfuse setup snippet off the internet today, there's a good chance it won't run. The Python SDK's v4 rewrite replaced the old API wholesale, and most tutorials — plus a lot of AI-generated code, because the models learned the old surface — still call functions that no longer exist. Here's the version that works in July 2026, and the one idea worth taking away.
The 10-second answer:pip install langfuse, set three env vars, and changeimport openaitofrom langfuse.openai import openai. That's a fully traced agent. Everything below is the rest of the kit.
Why the old code broke#
Langfuse v4.14.1 (current on PyPI as of 2026-07-20) is not "a client that ships data to Langfuse." Its own dependency list now pins opentelemetry-api, opentelemetry-sdk, and opentelemetry-exporter-otlp-proto-http — v4 is an OpenTelemetry instrumentation layer that happens to have Langfuse as one backend. The consequence is that the v2/v3 surface — langfuse.trace(), the StatefulTraceClient, hand-built .generation() calls — is gone. If a snippet starts with trace = langfuse.trace(...), it's pre-rewrite. Don't debug it; replace it.
Step 1 — install and authenticate#
pip install langfuse
Set three environment variables. Note the host var is LANGFUSE_BASE_URL in v4, not the old LANGFUSE_HOST:
export LANGFUSE_PUBLIC_KEY="pk-lf-..."
export LANGFUSE_SECRET_KEY="sk-lf-..."
export LANGFUSE_BASE_URL="https://cloud.langfuse.com" # or your self-hosted URL
Step 2 — the zero-effort path: the OpenAI drop-in#
The fastest way to a traced agent is to change a single import. Swap import openai for the Langfuse wrapper and every call becomes a traced generation — model, token counts, cost, and latency captured automatically:
from langfuse.openai import openai # was: import openai
resp = openai.chat.completions.create(
model="gpt-5.6",
messages=[{"role": "user", "content": "Summarize this support ticket."}],
)
Nothing else changes. This alone is enough to see your LLM calls in the dashboard.
Step 3 — trace your own functions with @observe#
Real agents are more than one model call — they retrieve, they call tools, they loop. Wrap your own functions with the @observe decorator and Langfuse nests the LLM and tool calls inside as child spans, so you get the full trajectory, not just the last completion:
from langfuse import observe, get_client
langfuse = get_client()
@observe()
def handle_request(ticket_id: str) -> str:
context = retrieve(ticket_id) # nested calls are captured automatically
return answer(context)
Step 4 — manual spans when you need control#
When you want to name a specific step or attach custom output, open an observation explicitly. This is the v4 replacement for the old trace.span() / trace.generation() calls:
langfuse = get_client()
with langfuse.start_as_current_observation(as_type="span", name="retrieve-context") as span:
docs = search(query)
span.update(output={"n_docs": len(docs)})
with langfuse.start_as_current_observation(as_type="generation", name="answer", model="gpt-5.6") as gen:
gen.update(output=text)
In a short-lived script, flush before you exit so nothing is lost on shutdown:
get_client().flush()
The non-obvious win: you're emitting OTel, not calling Langfuse#
Here's the part that changes how you should think about this. Because v4 emits standard OpenTelemetry spans, Langfuse is now just a place those spans land. Two things fall out of that, for free:
- Fan-out. The same instrumentation can point at Langfuse and any other OTLP-compatible backend at once. You are not locked into a single vendor's ingestion path — you're speaking a standard, and you choose the sinks.
- Fan-in. Any framework that is already OTel-instrumented — the OpenAI Agents SDK, LangChain, and others adopting the GenAI semantic conventions — can drop its traces into Langfuse with zero Langfuse-specific code. You instrument once, at the standard, not once per tool.
That's the real story of v4, and it's why the migration is worth doing now rather than patching old code. Observability stops being a Langfuse feature and becomes a property of your agent that you can redirect anywhere.
Where to go next#
Once traces are flowing, the payoff is turning them into evals — the same spans become the dataset you grade against. We walk that end to end in how to trace and evaluate an AI agent with Langfuse, and if you're still choosing a platform, Langfuse vs Laminar vs Arize Phoenix lays out the trade-offs. The setup above is the on-ramp; the evals are the product.



