---
title: Open Source Observability for Pipecat
sidebarTitle: Pipecat
logo: /images/integrations/pipecat_icon.svg
logoAppearance: dark
description: Trace real-time voice and multimodal conversations built with Pipecat using Langfuse.
---

# Pipecat Tracing Integration

This guide shows you how to integrate **Langfuse** with **Pipecat** for [observability and tracing](/docs/tracing) of real-time voice agents. By following these steps, you'll be able to monitor, debug and evaluate your Pipecat agents in the Langfuse dashboard.

> [Pipecat](https://www.pipecat.ai) ([repo](https://github.com/pipecat-ai/pipecat)) is an open-source Python framework for building real-time voice and multimodal conversational AI agents. Developed by Daily, it enables fully programmable AI voice agents and supports multimodal interactions, positioning itself as a flexible solution for developers looking to build conversational AI systems.

_Example of a Pipecat agent conversation in Langfuse._

## Features

- **Hierarchical Tracing**: Track entire conversations, turns, and service calls
- **Service Tracing**: Detailed spans for TTS, STT, and LLM services with rich context
- **TTFB Metrics**: Capture Time To First Byte metrics for latency analysis
- **Usage Statistics**: Track character counts for TTS and token usage for LLMs

## Trace Structure

Traces are organized hierarchically:

```
Conversation (conversation-uuid)
├── turn-1
│   ├── stt_deepgramsttservice
│   ├── llm_openaillmservice
│   └── tts_cartesiattsservice
└── turn-2
    ├── stt_deepgramsttservice
    ├── llm_openaillmservice
    └── tts_cartesiattsservice
    turn-N
    └── ...
```

This organization helps you track conversation-to-conversation and turn-to-turn.

**Important notes on this trace structure:**

1. **One trace = one full conversation**: Due to the way Pipecat structures its OpenTelemetry spans, a single trace represents one complete conversation. This differs from the typical Langfuse pattern where one trace equals one interaction, and full conversations are grouped under a [session](/docs/observability/features/sessions). With Pipecat, there's no need to group traces under a session—your entire conversation is already contained within a single trace.

2. **Default trace name**: By default, all traces are named `conversation` or the conversation uuid. See [Renaming Traces](#renaming-traces) below for an example of how to patch the spans to customize your trace name.

Learn more about Pipecat span attributes in the [Pipecat documentation](https://docs.pipecat.ai/server/utilities/opentelemetry).

## End-to-end Examples

- [Video guide](https://github.com/langfuse/langfuse-examples/tree/main/applications/langchat)
- [End-to-end example](https://github.com/pipecat-ai/pipecat-examples/tree/main/open-telemetry/langfuse)

## Get Started

Pipecat supports OpenTelemetry tracing, and Langfuse has an [OpenTelemetry endpoint](/docs/opentelemetry/get-started). By following these steps, you can enable Langfuse tracing for your Pipecat application.

<Steps>

### Obtain Langfuse API keys

Create a project in [Langfuse Cloud](https://cloud.langfuse.com) or [self-host](/self-hosting) Langfuse and copy your API keys.

### Environment Configuration

Base64 encode your Langfuse public and secret key:

```bash filename="terminal"
echo -n "pk-lf-1234567890:sk-lf-1234567890" | base64
```

Create a `.env` file with your API keys to enable tracing:

```bash filename=".env"
ENABLE_TRACING=true
# OTLP endpoint (defaults to localhost:4317 if not set)
OTEL_EXPORTER_OTLP_ENDPOINT="https://cloud.langfuse.com/api/public/otel" # 🇪🇺 EU data region
# Other Langfuse data regions include 🇺🇸 US: https://us.cloud.langfuse.com/api/public/otel, 🇯🇵 Japan: https://jp.cloud.langfuse.com/api/public/otel and ⚕️ HIPAA: https://hipaa.cloud.langfuse.com/api/public/otel
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Basic%20<base64_encoded_api_key>,x-langfuse-ingestion-version=4
# Set to any value to enable console output for debugging
# OTEL_CONSOLE_EXPORT=true
```

For more details, please refer to the Langfuse [OpenTelemetry documentation](/docs/opentelemetry/get-started).

### Add OpenTelemetry to your Pipeline Task

Enable tracing in your Pipecat application:

```python filename="main.py"
# Initialize OpenTelemetry with the http exporter
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

# Configured automatically from .env
exporter = OTLPSpanExporter()

setup_tracing(
    service_name="pipecat-demo",
    exporter=exporter,
)

# Enable tracing in your PipelineTask
task = PipelineTask(
    pipeline,
    params=PipelineParams(
        allow_interruptions=True,
        enable_metrics=True,  # Required for some service metrics
    ),
    enable_tracing=True,  # Enables both turn and conversation tracing
    conversation_id="customer-123",  # Optional - will auto-generate if not provided
)
```

For more details, please refer to the [OpenTelemetry Python Documentation](https://opentelemetry-python.readthedocs.io/).

### Add Trace Input and Output

Pipecat's service spans already carry each individual LLM call's messages, but the conversation input and output are not set at the trace level. You can patch Pipecat's service decorators to set the `langfuse.trace.input` and `langfuse.trace.output` attributes, capturing the first LLM call's messages as the trace input and the last LLM response as the trace output:

```python filename="main.py"
def patch_trace_input_output():
    from pipecat.utils.tracing import service_decorators
    original = service_decorators.add_llm_span_attributes
    first_call = [True]

    def patched(span, *args, **kwargs):
        original(span, *args, **kwargs)

        # Set the input of the first LLM call as the trace input
        if first_call[0] and kwargs.get("messages"):
            span.set_attribute("langfuse.trace.input", kwargs["messages"])
            first_call[0] = False

        # Set the output of each LLM call as the trace output (last one wins)
        orig_set = span.set_attribute
        def new_set(key, value):
            orig_set(key, value)
            if key == "output":
                orig_set("langfuse.trace.output", value)
        span.set_attribute = new_set

    service_decorators.add_llm_span_attributes = patched

# Apply patch before tracing setup
patch_trace_input_output()
```

`langfuse.trace.input` and `langfuse.trace.output` are trace-level attributes, which is why they can be set from a service span. They are deprecated in Langfuse v4 and retained for trace-level views and legacy LLM-as-a-judge evaluators — in the [observations-first data model](/docs/v4), the overall input and output belong on the root observation. Pipecat's conversation span is that root observation, but it is created internally and only accepts static attributes via `additional_span_attributes` on `PipelineTask`, so runtime values such as the first user message still need the trace-level attributes above. See [moving trace input and output](/integrations/native/opentelemetry/migration-to-v4#move-trace-input-and-output) for the background.

To attach context that is known before the pipeline runs, pass it to the conversation span directly instead:

```python filename="main.py"
task = PipelineTask(
    pipeline,
    params=PipelineParams(enable_metrics=True),
    enable_tracing=True,
    conversation_id="customer-123",
    additional_span_attributes={"langfuse.session.id": "session-abc"},
)
```

### Renaming Traces (Optional) [#renaming-traces]

By default, all Pipecat traces are named `conversation` or use the conversation UUID. To customize the trace name, extend the patch to set the `langfuse.trace.name` attribute:

```python filename="main.py"
def patch_trace_name():
    from pipecat.utils.tracing import service_decorators
    original = service_decorators.add_llm_span_attributes
    first_call = [True]

    def patched(span, *args, **kwargs):
        original(span, *args, **kwargs)

        # Set a custom trace name on the first LLM call
        if first_call[0]:
            span.set_attribute("langfuse.trace.name", "pipecat-chatbot")
            first_call[0] = False

    service_decorators.add_llm_span_attributes = patched

# Apply patch before tracing setup
patch_trace_name()
```

You can combine both patches into a single function if you want to set the trace name, input, and output together.

</Steps>

## Understanding the Traces

- **Conversation Spans**: The top-level span representing an entire conversation
- **Turn Spans**: Child spans of conversations that represent each turn in the dialog
- **Service Spans**: Detailed service operations nested under turns
- **Service Attributes**: Each service includes rich context about its operation:
  - **TTS**: Voice ID, character count, service type
  - **STT**: Transcription text, language, model
  - **LLM**: Messages, tokens used, model, service configuration
- **Metrics**: Performance data like `metrics.ttfb_ms` and processing durations

## How It Works

The tracing system consists of:

1. **TurnTrackingObserver**: Detects conversation turns
2. **TurnTraceObserver**: Creates spans for turns and conversations
3. **Service Decorators**: `@traced_tts`, `@traced_stt`, `@traced_llm` for service-specific tracing
4. **Context Providers**: Share context between different parts of the pipeline

## Troubleshooting

- **No Traces in Langfuse**: Ensure that your credentials are correct and follow this [troubleshooting guide](/faq/all/missing-traces)
- **Missing Metrics**: Check that `enable_metrics=True` in PipelineParams
- **Connection Errors**: Verify network connectivity to Langfuse
- **Exporter Issues**: Try the Console exporter (`OTEL_CONSOLE_EXPORT=true`) to verify tracing works

## References

- [End-to-end example](https://github.com/pipecat-ai/pipecat-examples/tree/main/open-telemetry/langfuse)
- [Pipecat Tracing Documentation](https://docs.pipecat.ai/server/utilities/opentelemetry)

## GitHub Discussions

<!-- agent-instructions -->

---

## Agent Instructions

This page is part of the [Langfuse](https://langfuse.com) documentation, published as plain Markdown for AI agents. Every page is available as Markdown by appending `.md` to its URL, or by sending an `Accept: text/markdown` header. This page: `https://langfuse.com/integrations/frameworks/pipecat.md`.

### Querying these docs

If the answer is not on this page, query the documentation instead of guessing:

- **Semantic search** across all Langfuse docs, returning an answer with the relevant pages and excerpts. Ask a specific, self-contained question:

  ```bash
  curl -sG "https://langfuse.com/api/search-docs" --data-urlencode "query=How do I trace a LangGraph agent?"
  ```

- **Index of every page**: <https://langfuse.com/llms.txt>, with per-section indexes [llms-docs.txt](https://langfuse.com/llms-docs.txt), [llms-integrations.txt](https://langfuse.com/llms-integrations.txt), and [llms-self-hosting.txt](https://langfuse.com/llms-self-hosting.txt).

### Before writing Langfuse code

- **Install the [Langfuse Agent Skill](https://langfuse.com/docs/api-and-data-platform/features/agent-skill).** It encodes Langfuse's own best practices for instrumentation, prompt management, and evaluation, and materially improves results.
- **Read [What does a good trace look like?](https://langfuse.com/docs/observability/best-practices.md)** before instrumenting an application.
- **Verify endpoints, parameters, and response fields** against the [API reference](https://api.reference.langfuse.com) instead of inferring them from code examples.
- **Use the [Langfuse CLI](https://langfuse.com/docs/api-and-data-platform/features/cli)** (`npx langfuse-cli api <resource> <action>`) to read or write traces, prompts, datasets, and scores from the terminal.

Found an error in these docs? Please open an issue at <https://github.com/langfuse/langfuse-docs/issues>.
