from langfuse import observe). If your app imports langfuse.decorators or langfuse.callback, see older Langfuse SDK versions.
Use a coding agent to migrate
Use a coding agent to migrate
Choose a path
Get the project-scoped API key for the HoneyHive project that receives your traces. Go to Settings > Project > API Keys, open the Project tab, and click Create API Key. Copy the key from the dialog and store it asHH_API_KEY - it is only shown once.
This flow runs experiments and reads results, so it needs a project API key. To send its traces with an ingestion key instead, also set HH_INGESTION_API_KEY; the SDK uses each key where it applies.
- Path A: start here if your Python app calls
@observe,langfuse.openai, orCallbackHandler. - Path B: use this path if your app already emits OpenTelemetry, OpenInference, OpenLLMetry, or OTel GenAI spans. Non-Python apps use this path.
Path A: swap the Python SDK
Replace each Langfuse integration in your Python app.1. Install HoneyHive
HoneyHive requires Python 3.11 or newer. Run these commands from your app’s directory. If it already has an active virtual environment, skip the first two commands."honeyhive[openinference-langchain]". See the integrations overview for other libraries.
2. Replace @observe with @trace
OpenAIInstrumentor traces the OpenAI call without @trace. Keep @trace when you want to preserve the Langfuse @observe() function as a parent chain event with its own inputs and output.
Run the HoneyHive version and inspect the session. Confirm the parent chain event, the model call under it, and the session user ID and tags.
enrich_session() applies to the current HoneyHive session rather than a with block. If you used a Langfuse session_id for a multi-turn conversation, create or reuse a HoneyHive session for that conversation.
Keep tracer.flush() at the end of scripts, notebooks, and Lambda handlers. Long-running servers flush on a timer.
3. Replace nested observations
span to a chain event, each generation to a model event, and each tool call to a tool event.
When you call enrich_span_context(), pass tracer_instance=tracer and set attributes={"honeyhive_event_type": "chain"} (or "model" / "tool"). There is no event_type argument. You can also add @trace to child functions. See custom spans for both patterns.
4. Replace the Langfuse OpenAI client
5. Replace the LangChain callback
Path B: send OpenTelemetry spans to HoneyHive
Keep your existing instrumentation and point its standard OTLP/HTTP exporter at HoneyHive.1. Configure the exporter
HoneyHive receives OTLP/HTTP traces at:api.dp1.us.honeyhive.ai:
/v1/traces to OTEL_EXPORTER_OTLP_ENDPOINT. If your exporter expects a traces-only URL, set the full path:
http/protobuf, send OTLP/HTTP JSON.
Langfuse v4 filters spans to LLM-focused instrumentation by default. A generic OTLP exporter can also send HTTP, database, queue, and framework spans. Recreate your existing filter in the SDK or Collector if you want to keep the same span set.
To send spans to both products during migration, configure two exporters in your OpenTelemetry Collector.
2. Send a request
Run one request through your app, then open Traces in HoneyHive. Check the trace hierarchy, inputs, outputs, and event types. HoneyHive maps OpenInference and OTel GenAI fields (inputs, outputs, model, tokens, span kind) to native fields. Other OTLP attributes, includinglangfuse.* attributes, remain in metadata but are not translated into HoneyHive fields. Remap the values you still need, and recreate Langfuse concepts such as public and bookmarked separately. See API mappings for fields that have a HoneyHive equivalent.
Move scores and evaluators
Write Langfuse scores as HoneyHive metrics on the current span or session:
After you import a dataset, run your latest baseline with
evaluate(dataset_id=...). Use the same judge prompt, model, and settings for comparison.
To keep migrated evaluators and datasets in version control, follow Config as Code and apply them with the HoneyHive CLI or CI.
Move datasets
For text and structured data, export your Langfuse dataset as CSV, then upload it to HoneyHive. Confirm that the row count matches before you run an experiment. For multimodal datasets, export media separately and replace Langfuse media references with values your application can load.Copy a dataset with the Python SDK
Copy a dataset with the Python SDK
Move prompts
Use the Langfuse and HoneyHive Python SDKs to copy each prompt version you still use. HoneyHive stores every template as a message array, so the script converts a Langfuse text prompt to oneuser message. It preserves the remaining Langfuse configuration values without requiring manual Playground entry.
Use this label mapping when you deploy:
Langfuse moves the
latest label whenever you create a version. HoneyHive environments point to configurations you deploy explicitly, so choose which version reaches dev, staging, or prod.
Copy a prompt version with the Python SDK
Copy a prompt version with the Python SDK
Set the source prompt and destination configuration:The script stores the remaining Langfuse
HH_PROMPT_MODEL is a fallback for Langfuse prompts whose config does not include a model.config fields in hyperparameters, including provider-specific fields such as tools, tool_choice, and response schemas. Your application can forward those fields to its model client. To use tools or response formats in the HoneyHive Playground, map them to the native selectedFunctions, functionCallParams, forceFunction, and responseFormat parameters.Run the script once per prompt version. Set HH_PROMPT_ENVS to every HoneyHive environment that version serves, such as staging,prod. Keep one configuration per prompt version instead of creating duplicate configurations with the same name. To promote a different version later, update the env lists on the affected configurations.Langfuse message placeholders have no direct HoneyHive configuration equivalent. The script stops when it finds one so you can insert those runtime messages in application code instead of silently dropping them.Use a coding agent to migrate application prompts
Use a coding agent to migrate application prompts
Paste this prompt into your coding agent:
langfuse.get_prompt("my-prompt", label="production") to version 3, find my-prompt-v3 in honeyhive.configurations.list() with prod in its env list:
prompt_text or messages, plus configuration.parameters.hyperparameters, to the corresponding model client.
Check that it worked
- Send traffic that covers a normal request, a tool call, and an error.
- Open Traces in the project that owns your
HH_API_KEY. - Confirm the span hierarchy, model name, token usage, user ID, and custom metadata.
- Compare the dataset row count with Langfuse, then run one baseline experiment with
evaluate(dataset_id=...).
observe, get_client, CallbackHandler, and langfuse.openai. Keep tracer.flush() in scripts and other short-lived processes.
Troubleshooting
Traces do not appear
- Confirm
HH_API_KEYis set and belongs to the HoneyHive project you opened. - Call
HoneyHiveTracer.init(...)beforeinstrument()and before you create model clients. - Pass
tracer_provider=tracer.providerto the instrumentor. - Set
HH_API_URLor passserver_url=toHoneyHiveTracer.initwhen you use self-hosted HoneyHive. - Call
tracer.flush()before a script, notebook, or Lambda handler exits.
OTLP environment variables have no effect
RemoveLangfuseSpanProcessor and configure a standard OTLP exporter or OpenTelemetry Collector. OTEL_EXPORTER_* variables do not change where the Langfuse processor sends spans.
Nested spans are missing
Decorate child functions with@trace or wrap blocks in enrich_span_context(). A parent @trace does not create child spans around undecorated calls.
OpenAI calls are duplicated
Removefrom langfuse.openai import openai or OpenAI before you enable OpenAIInstrumentor. Use the standard openai package.
LangChain calls appear twice
Remove the LangfuseCallbackHandler after you enable LangChainInstrumentor. Do not attach both to one invocation.
Dataset rows appear in metadata
Make sureDatapointMapping.inputs and ground_truth exactly match keys in each row. HoneyHive stores unmapped keys as metadata.
Appendix
API mappings
Use these tables to replace other Langfuse calls in your app.Older Langfuse SDK versions
For Langfuse Python SDK v2 and v3, either update to v4 first or replace the older imports directly:Optional historical backfill
HoneyHive does not provide a Langfuse importer. To backfill selected historical traces, recreate them with the current Sessions and Events APIs. Create new HoneyHive session and event UUIDs, and keep the original Langfuse IDs inmetadata.
Request fields=core,basic,time,io,metadata,model,usage,trace_context from the Langfuse Observations API v2. The endpoint returns only core,basic by default. Set expandMetadata to a comma-separated list of metadata keys whose values must not be truncated at 200 characters. Bound each request with fromStartTime and toStartTime, then follow meta.cursor until it is empty.
Export scores separately with fields=details,subject from the Langfuse Scores API v3, following its cursor until it is empty. The Observations API does not return scores.
Trace, observation, and score field mappings
Trace, observation, and score field mappings
Trace to session
The Langfuse Observations API repeats trace context on each observation. Create one HoneyHive session per uniquetraceId and use fields from the root observation.POST /v1/sessions does not accept external_id. Store the Langfuse trace ID in session metadata.Generation to model event
The Langfuse Observations API v2 returns input and output as raw strings. Decode valid JSON first. Keep decoded objects as they are. Wrap arrays, scalars, and plain strings in a named field such as
{"value": ...}. HoneyHive session and event inputs and outputs must be objects, and event inputs is required.Observation type to event type
Scores
POST /v1/sessions does not accept top-level metrics or feedback, but POST /v1/events accepts metrics. For an observation-subject score, put the selected numeric or boolean value in the mapped event’s metrics object so HoneyHive can filter and chart it. Preserve the complete score record under metadata.langfuse_scores[], including id, name, value, data_type, subject, comment, and source. For a trace-subject score, keep that record in the mapped session’s metadata. Langfuse session and experiment subjects have no one-to-one HoneyHive backfill target, so preserve their complete subject object and choose the corresponding imported session or experiment workflow. For live traffic, use tracer.enrich_span(metrics=...) or tracer.enrich_session(metrics=...).Data to recreate
Langfusepublic, bookmarked, prompt templates, dataset run history, and annotation queues do not map to historical session or event fields. Recreate the prompts, datasets, and review workflows you still use.Related
Tracing quickstart
Send a first OpenAI trace with OpenInference
Custom spans
Replace @observe with @trace and context managers
LangChain integration
Instrument LangChain and LangGraph without a callback handler
Run an experiment
Re-run a baseline with evaluate(dataset_id=…) after you import a dataset
Need help migrating from self-hosted Langfuse? Contact us.