Python v4 → v5
For most users, v5 is a small upgrade. If you trace with @observe, start_as_current_observation(), or an integration, and you create scores and fetch prompts, your code keeps working as is. v5 needs Python 3.11+ and Langfuse Cloud or self-hosted Langfuse v4.59.0 or later.
Most removals in v5 were already deprecated in v4. If your code runs on v4 without a DeprecationWarning from langfuse, you're most likely unaffected apart from the minimum versions, direct api.scores calls, and run_batched_evaluation(). Python hides DeprecationWarning by default outside __main__, so check with python -W default::DeprecationWarning or under pytest.
pip install --upgrade "langfuse>=5"host and the LANGFUSE_HOST environment variable keep working as before.
Are you affected?
You only need to change something if one of these applies to you.
New in v5:
- You self-host Langfuse v3, or v4 older than v4.59.0, or run Python 3.10,
openai<1, orlangchain-core<1→ Minimum versions - You call
api.scores.createorapi.legacy.score_v1.*directly →api.scorestakes request objects - You call
api.scores_v3.get_many_v3→ Score reads move toapi.scores.get_many - You call
run_batched_evaluation()→ Batched evaluation reads observations only - A proxy between your app and Langfuse rejects gzip-compressed requests → Under the hood
Previously deprecated in v4, now removed:
- You call deprecated
langfuse.api.*methods, for exampleapi.trace.get,api.sessions,api.legacy.*, orapi.scores.get_many→ Deprecated Public API methods removed - You call
set_current_trace_io()orspan.set_trace_io()→ Trace input/output setters removed - You call
get_dataset_runs(),get_dataset_run(), ordelete_dataset_run()→ Dataset run helpers removed - You pass
blocked_instrumentation_scopes→blocked_instrumentation_scopesremoved
If none of these apply, upgrade and you're done.
Breaking changes
These are new in v5. Ordered by how many users they affect.
Minimum versions
Affects: self-hosted Langfuse v3 or older than v4.59.0, Python 3.10, and the OpenAI and LangChain integrations on older libraries.
| Requirement | v5 | If not met |
|---|---|---|
| Langfuse | Cloud, or self-hosted v4.59.0 or later | Unsupported. Upgrade Langfuse first, or stay on the previous SDK major |
| Python | >=3.11 | pip install langfuse resolves to the latest v4 release |
| OpenAI | openai>=1.0 | The langfuse.openai integration no longer supports pre-1.0 SDKs |
| LangChain | langchain-core>=1 | ModuleNotFoundError when importing langfuse.langchain with an older langchain-core |
If you self-host Langfuse v3, stay on Python SDK v4. See the self-hosted compatibility matrix.
pip install --upgrade "langfuse>=5" "langchain-core>=1"The LangChain CallbackHandler imports only from langchain_core now, so the langchain meta-package is no longer needed. Its import path and usage are unchanged.
api.scores takes request objects
Affects: code that calls langfuse.api.scores.create(...) or langfuse.api.legacy.score_v1.* directly. create_score(), span.score(), and span.score_trace() are unchanged.
Breaks: TypeError for the old api.scores.create keyword arguments, and AttributeError for api.legacy.score_v1.
api.scores.create()now takes a list ofCreateScoreRequestobjects asrequest=, and returnsCreateScoresResponse:CreateScoreBatchResponsewhen all scores are accepted, orCreateScoreBatchResultswith accepted/rejected counts and errors.api.legacy.score_v1.delete(score_id=...)moves toapi.scores.delete(score_id=...).api.legacy.score_v1.create(...)was already a deprecated alias ofapi.scores.createin v4. Useapi.scores.create(request=[CreateScoreRequest(...)]).
v4:
langfuse.api.scores.create(name="accuracy", value=0.9, trace_id="trace-id")
langfuse.api.legacy.score_v1.delete(score_id="score-id")v5:
from langfuse import get_client
from langfuse.api import CreateScoreRequest
langfuse = get_client()
langfuse.api.scores.create(
request=[CreateScoreRequest(name="accuracy", value=0.9, trace_id="trace-id")]
)
langfuse.api.scores.delete(score_id="score-id")Score reads move to api.scores.get_many
Affects: code that calls langfuse.api.scores_v3.get_many_v3(...) or langfuse.async_api.scores_v3.get_many_v3(...).
Breaks: AttributeError, because api.scores_v3 no longer exists.
Scores API v3 reads moved into the scores namespace, next to create and delete. The arguments and the GetScoresV3Response response are unchanged. The v4 api.scores.get_many(score_ids=...) read Scores API v2; in v5, the same method name reads Scores API v3 and filters by id= instead of score_ids=.
v4:
scores = langfuse.api.scores_v3.get_many_v3(trace_id="trace-id", fields="subject")v5:
from langfuse import get_client
langfuse = get_client()
scores = langfuse.api.scores.get_many(trace_id="trace-id", fields="subject")Batched evaluation reads observations only
Affects: code that calls langfuse.run_batched_evaluation().
Breaks (new in v5, no prior deprecation): TypeError for scope, fetch_trace_fields, and _additional_trace_tags, and ValueError when resuming with a v4 token or with a different filter. The function now reads from the v2 observations API and evaluates observations only.
scopeis removed. To evaluate whole traces, filter for the observations that represent them, for example bynameortype.fetch_trace_fieldsis renamed tofields(default"core,basic,io,metadata"). Available field groups:core,basic,time,io,metadata,model,usage,prompt,metrics,trace_context.- The mapper receives
item=ObservationV2.inputandoutputare raw strings. filtermust be a v2 filter JSON array._additional_trace_tagsis removed.- Resume tokens from v4 can't be reused, and resuming with a different filter raises a
ValueError.
v4:
def trace_mapper(*, item):
return EvaluatorInputs(input=item.input, output=item.output, expected_output=None)
langfuse.run_batched_evaluation(
scope="traces",
mapper=trace_mapper,
filter='{"tags": ["production"]}',
fetch_trace_fields="core,io",
evaluators=[accuracy],
)v5:
from langfuse import EvaluatorInputs, get_client
langfuse = get_client()
def observation_mapper(*, item, **kwargs):
return EvaluatorInputs(
input=item.input,
output=item.output,
expected_output=None,
metadata={"trace_id": item.trace_id},
)
langfuse.run_batched_evaluation(
mapper=observation_mapper,
filter='[{"type": "string", "column": "type", "operator": "=", "value": "GENERATION"}]',
fields="core,basic,io,model",
evaluators=[accuracy],
)Previously deprecated, now removed
v4 already marked each of these as deprecated and named the replacement. If you moved to the replacement, nothing changes.
Deprecated Public API methods removed
Affects: code that calls the endpoints below through langfuse.api.*.
Previously deprecated in v4, now removed. Each of these methods raised a DeprecationWarning in v4 that named its replacement. In v5 they raise AttributeError, and there is no api.legacy namespace anymore. For full replacement guidance, see the SDK method quick reference.
| Removed | Replacement |
|---|---|
api.trace.get(...), api.trace.list(...) | api.observations.get_many(trace_id=..., ...) |
api.sessions.* | api.observations.get_many(session_id=..., ...) |
api.legacy.observations_v1.* | api.observations.get_many(...) |
api.legacy.metrics_v1.metrics(...) | api.metrics.metrics(...) |
api.scores.get_many(...) (v2), api.scores.get_by_id(...) | api.scores.get_many(...) (Scores API v3) |
api.dataset_run_items.* | api.experiments.list_items(...) or the experiment runner |
api.datasets.get_run(...), .get_runs(...), .delete_run(...) | Dataset run helpers removed |
api.trace keeps delete and delete_multiple. api.datasets keeps list, get, and create.
api.scores.get_many keeps its name but now reads Scores API v3; see Score reads move to api.scores.get_many.
v4:
trace = langfuse.api.trace.get("trace-id")v5:
observations = langfuse.api.observations.get_many(trace_id="trace-id", fields="core,basic,io")Removed types include Trace, TraceWithDetails, TraceWithFullDetails, Traces, Observation, ObservationsView, ObservationsViews, Session, SessionWithTraces, PaginatedSessions, DatasetRun, DatasetRunItem, DatasetRunWithItems, PaginatedDatasetRuns, PaginatedDatasetRunItems, CreateDatasetRunItemRequest, DeleteDatasetRunResponse, the ScoreV1 family, GetScoresResponse*, the v1 MetricsResponse, and the sdk-log ingestion event. langfuse.model no longer re-exports DatasetRun, Observation, or TraceWithFullDetails.
Trace input/output setters removed
Affects: code that calls set_current_trace_io() or span.set_trace_io(), or sets the trace-level input/output attributes.
Previously deprecated in v4, now removed. Both methods raised a DeprecationWarning in v4 that pointed to propagate_attributes() for trace attributes. In v5 they raise AttributeError. Trace input and output now come from the root observation.
v4:
from langfuse import get_client
langfuse = get_client()
with langfuse.start_as_current_observation(as_type="span", name="request") as span:
result = call_llm(query)
langfuse.set_current_trace_io(input=query, output=result)v5:
from langfuse import get_client
langfuse = get_client()
with langfuse.start_as_current_observation(as_type="span", name="request") as span:
result = call_llm(query)
span.update(input=query, output=result)
# or, inside the active root span:
# langfuse.update_current_span(input=query, output=result)set_current_trace_as_public() and span.set_trace_as_public() are unchanged. If you still use trace-level LLM-as-a-judge evaluators, migrate them to observation-level evaluators.
Dataset run helpers removed
Affects: code that calls get_dataset_runs(), get_dataset_run(), or delete_dataset_run().
Previously deprecated in v4, now removed. The endpoints behind these helpers were deprecated in v4, and the deprecated API migration guide lists the experiments API as their replacement. In v5 they raise AttributeError. "Dataset run" and "experiment" mean the same thing.
| Removed | Replacement |
|---|---|
langfuse.get_dataset_runs(dataset_name=...) | langfuse.api.experiments.list(dataset_id=..., from_start_time=...) |
langfuse.get_dataset_run(dataset_name=..., run_name=...) | langfuse.api.experiments.list(...) and .list_items(...) |
langfuse.delete_dataset_run(dataset_name=..., run_name=...) | List the experiment items, then langfuse.api.trace.delete_multiple(...) |
v4:
runs = langfuse.get_dataset_runs(dataset_name="qa-set")
run = langfuse.get_dataset_run(dataset_name="qa-set", run_name="baseline")
langfuse.delete_dataset_run(dataset_name="qa-set", run_name="baseline")v5:
from langfuse import get_client
langfuse = get_client()
dataset = langfuse.get_dataset("qa-set")
# No experiment item starts before its dataset was created, so this covers every run.
since = dataset.created_at
# List experiments (dataset runs) for a dataset
experiments = langfuse.api.experiments.list(dataset_id=dataset.id, from_start_time=since)
# List the items of one experiment and follow cursor pagination
trace_ids = set()
cursor = None
while True:
page = langfuse.api.experiments.list_items(
dataset_id=dataset.id,
experiment_name="baseline",
from_start_time=since,
cursor=cursor,
)
trace_ids.update(item.trace_id for item in page.data)
cursor = page.meta.cursor
if not cursor:
break
# Delete the experiment's traces (also deletes their observations and scores)
ids = list(trace_ids)
for i in range(0, len(ids), 1000):
langfuse.api.trace.delete_multiple(trace_ids=ids[i : i + 1000])There is no experiment-delete API. Deleting the traces also deletes their observations and scores. See Dataset runs → Experiments for details.
blocked_instrumentation_scopes removed
Affects: code that passes blocked_instrumentation_scopes to Langfuse(...).
Previously deprecated in v4, now removed. v4 raised a DeprecationWarning that pointed to should_export_span. In v5 the parameter raises TypeError. Compose should_export_span with the default filter.
v4:
from langfuse import Langfuse
langfuse = Langfuse(blocked_instrumentation_scopes=["sqlite", "requests"])v5:
from langfuse import Langfuse
from langfuse.span_filter import is_default_export_span
blocked = {"sqlite", "requests"}
langfuse = Langfuse(
should_export_span=lambda span: (
is_default_export_span(span)
and (
span.instrumentation_scope is None
or span.instrumentation_scope.name not in blocked
)
)
)New features
These need no code changes.
- Experiment links.
result.experiment_idandresult.experiment_urllink directly to the experiment comparison view. - Typed metadata filters. Numeric and boolean metadata keeps its type, and nested objects can be filtered by dotted path, such as
a.b = 1. - Batch score creation.
api.scores.create()accepts a list ofCreateScoreRequestobjects. - Experiment records. Run evaluations are stored for local-data runs too. Dataset versions are recorded on items as
langfuse.experiment.item.version. - Lighter LangChain dependency. The
CallbackHandlerneeds onlylangchain-core.
Under the hood
None of these need code changes. Each one has a setting if you need different behavior.
- Scores are sent in batches to
POST /api/public/scoresinstead of the legacy ingestion endpoint.create_score(),span.score(),span.score_trace(),flush_at, andflush_intervalwork as before. If the server accepts only part of a batch (HTTP 207), the SDK logs the accepted and rejected counts and the errors, and doesn't retry the rejected scores. Other 4xx responses are logged and not retried. Network errors, 429, and 5xx are retried with backoff. - Span batches are gzip-compressed. If a proxy rejects compressed requests, set
Langfuse(otel_compression="none")orLANGFUSE_OTEL_COMPRESSION=none. The setting is read in this order:otel_compression,LANGFUSE_OTEL_COMPRESSION,OTEL_EXPORTER_OTLP_TRACES_COMPRESSION,OTEL_EXPORTER_OTLP_COMPRESSION, then thegzipdefault. Values aregzipornone(case-insensitive), and an invalid value falls through to the next setting. A customspan_exporteris not changed. - Spans carry
x-langfuse-ingestion-version: 4, which enables real-time processing on Langfuse v4. To opt out, passadditional_headers={"x-langfuse-ingestion-version": "3"}. A customspan_exporterdoesn't get this header automatically. - The default span filter's GenAI check requires the
gen_ai.prefix, dot included, so attributes likegen_ai_customno longer count. - Experiments are recorded through OpenTelemetry.
run_experiment()sends experiment and item attributes on its spans instead of callingPOST /api/public/dataset-run-items.
Last updated on