Skip to main content

Overview

If you already instrument your LLM app with Langfuse — whether using @observe decorators or the LangChain CallbackHandler — you can send the same traces to Galtea for evaluation by swapping a single import. Under the hood, one span per function call flows to both Langfuse and Galtea simultaneously.

Real-Time Dual Export

Every span flows to both Langfuse and Galtea simultaneously — no polling, no extra API credentials needed.

Transparent to Langfuse

Nothing changes in Langfuse. Your dashboard, trace IDs, alerts, and URLs are completely unaffected.

Any Init Order

Initialize Galtea or Langfuse first — both orders work. The libraries detect each other automatically.

Selective Export

Galtea only exports traces when you explicitly link an inference_result_id. Otherwise, it does nothing.
Worried about impact on your Langfuse setup? See the Integration Guide for a detailed breakdown of what changes and what doesn’t.

Setup

1. Install

Requires Langfuse v3.0.0+ — v2.x is not supported.
If you use Langfuse’s LangChain CallbackHandler, install with LangChain support:

2. Initialize the Galtea client

Initialization order with Langfuse doesn’t matter.
To get your API key, go to the settings page on the Galtea platform.

3. Swap the import

Replace your Langfuse observe import with the Galtea wrapper. The decorator API is identical — all @observe parameters (name, as_type, etc.) work the same way.

Instrumenting Your Agent

Decorate your agent functions with @observe, exactly as you would with Langfuse. Nested decorators create a parent-child trace hierarchy automatically.
When my_agent("Hello", inference_result_id=ir_id) runs, Galtea receives a 3-level trace:

Observation types

Use the as_type parameter on @observe to set the observation type. Each type maps to a Galtea trace type automatically:
Unknown Langfuse observation types are automatically mapped to SPAN in Galtea. Your traces are never dropped.

Context manager API

If you use Langfuse’s start_as_current_observation context manager instead of the @observe decorator, Galtea provides an equivalent wrapper:
Both APIs can be mixed freely — an @observe-decorated function can be called inside a start_as_current_observation block (or vice versa) and the parent-child hierarchy is preserved.
Only the root start_as_current_observation call needs the Galtea wrapper. Child calls on yielded spans (e.g., root.start_as_current_observation(...)) are native Langfuse — no change needed.

LangChain CallbackHandler

If you use Langfuse’s CallbackHandler for LangChain tracing, Galtea provides an equivalent wrapper:
Your handler initialization stays the same — create it once at app startup and pass it to any LangChain .invoke(), .batch(), or .stream() call. To link traces to Galtea, call set_inference_result_id before each invocation:
The handler automatically manages set_context / clear_context around LangChain callback lifecycles — no context managers or manual cleanup needed. You can also pass inference_result_id directly in the constructor if you prefer to create a handler per request.
The CallbackHandler requires langchain to be installed. Install it with: pip install langchain
All three APIs can be mixed freely — for example, an @observe-decorated function can pass a CallbackHandler to a LangChain chain inside it, and the parent-child trace hierarchy is preserved.

Linking Traces to an Inference Result

Galtea only exports trace data when an inference_result_id is explicitly linked. Without it, Galtea does nothing — no data is sent, no spans are modified. There are three ways to link traces: When using generate() or simulate(), the SDK manages inference_result_id automatically — zero extra code:

Passing inference_result_id as a kwarg

Pass inference_result_id to the outermost @observe-decorated function. The wrapper manages the trace context automatically:
The inference_result_id kwarg is consumed by the wrapper — it does not reach your function’s parameters.

Manual set_context / clear_context

For full control, manage the context lifecycle yourself:
set_context must wrap outside the @observe-decorated call. If called inside the decorated function, the outermost span will be missed.

How It Works

Both Galtea and Langfuse use OpenTelemetry internally. When both are initialized, they share the same tracing infrastructure — each span created by @observe flows to both Langfuse cloud and the Galtea API. The Galtea SDK exporter only sends spans that have an inference_result_id linked (it posts them to the Galtea REST Trace API); everything else is skipped client-side. Langfuse observation attributes (type, input, output, metadata) are automatically mapped to their Galtea equivalents. (Spans exported directly to the Galtea public OTel endpoint follow different rules; see Send OpenTelemetry Traces to Galtea.)