Observability for Pipecat with Opik

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.

This guide explains how to integrate Opik with Pipecat for observability and tracing of real-time voice agents, enabling you to monitor, debug, and evaluate your Pipecat agents in the Opik dashboard.

Account Setup

Comet provides a hosted version of the Opik platform, simply create an account and grab your API Key.

You can also run the Opik platform locally, see the installation guide for more information.

Key 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
  • Real-time Monitoring: Monitor voice agent performance and conversation quality

Getting Started

Installation

To use Pipecat with Opik, you’ll need to have both the pipecat-ai and opik packages installed:

$pip install pipecat-ai opik opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp

Configuring Opik

Configure the Opik Python SDK for your deployment type. See the Python SDK Configuration guide for detailed instructions on:

  • CLI configuration: opik configure
  • Code configuration: opik.configure()
  • Self-hosted vs Cloud vs Enterprise setup
  • Configuration files and environment variables

Configuring Pipecat

In order to configure Pipecat, you will need to have your API keys for the services you’re using (OpenAI, Deepgram, etc.). You can set them as environment variables:

{pytest_codeblocks_skip=true}
$export OPENAI_API_KEY="YOUR_OPENAI_API_KEY"
>export DEEPGRAM_API_KEY="YOUR_DEEPGRAM_API_KEY"

Or set them programmatically:

1import os
2import getpass
3
4if "OPENAI_API_KEY" not in os.environ:
5 os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
6
7if "DEEPGRAM_API_KEY" not in os.environ:
8 os.environ["DEEPGRAM_API_KEY"] = getpass.getpass("Enter your Deepgram API key: ")
9
10# Set project name for organization
11os.environ["OPIK_PROJECT_NAME"] = "pipecat-voice-agent-demo"

OpenTelemetry Integration

Pipecat supports OpenTelemetry tracing, and Opik has an OpenTelemetry endpoint. By following these steps, you can enable Opik tracing for your Pipecat application.

Environment Configuration

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

$ENABLE_TRACING=true
># OTLP endpoint for Opik Cloud
>OTEL_EXPORTER_OTLP_ENDPOINT="https://www.comet.com/opik/api/v1/private/otel"
># OTLP headers with your Opik API key
>OTEL_EXPORTER_OTLP_HEADERS="Authorization=<your-opik-api-key>,Comet-Workspace=default"
># Set to any value to enable console output for debugging
># OTEL_CONSOLE_EXPORT=true

For self-hosted Opik instances:

$ENABLE_TRACING=true
># OTLP endpoint for self-hosted Opik
>OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:5173/api/v1/private/otel"
># OTLP headers for self-hosted
>OTEL_EXPORTER_OTLP_HEADERS="projectName=your-project-name"

Add OpenTelemetry to your Pipeline Task

Enable tracing in your Pipecat application:

1from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
2from opentelemetry import trace
3from opentelemetry.sdk.trace import TracerProvider
4from opentelemetry.sdk.trace.export import BatchSpanProcessor
5from opentelemetry.sdk.resources import Resource
6from pipecat.pipeline.pipeline import Pipeline
7from pipecat.pipeline.runner import PipelineRunner
8from pipecat.pipeline.task import PipelineTask, PipelineParams
9from pipecat.services.openai import OpenAILLMService
10from pipecat.services.deepgram import DeepgramSTTService
11from pipecat.services.cartesi import CartesiTTSService
12from pipecat.transports.websocket import WebSocketTransport
13from pipecat.frames.frames import TextFrame
14import os
15
16# Initialize OpenTelemetry with the OTLP exporter
17def setup_tracing(service_name="pipecat-demo"):
18 # Create resource
19 resource = Resource.create({
20 "service.name": service_name,
21 "service.version": "1.0.0",
22 })
23
24 # Create tracer provider
25 tracer_provider = TracerProvider(resource=resource)
26 trace.set_tracer_provider(tracer_provider)
27
28 # Create OTLP exporter
29 exporter = OTLPSpanExporter(
30 endpoint=os.getenv("OTEL_EXPORTER_OTLP_ENDPOINT"),
31 headers=os.getenv("OTEL_EXPORTER_OTLP_HEADERS")
32 )
33
34 # Add span processor
35 span_processor = BatchSpanProcessor(exporter)
36 tracer_provider.add_span_processor(span_processor)
37
38 return tracer_provider
39
40# Configure tracing
41setup_tracing("pipecat-voice-agent")
42
43# Create your Pipecat pipeline
44async def main():
45 # Create transport
46 transport = WebSocketTransport("ws://localhost:8765")
47
48 # Create services
49 llm = OpenAILLMService(
50 api_key=os.getenv("OPENAI_API_KEY"),
51 model="gpt-4o-mini"
52 )
53
54 stt = DeepgramSTTService(
55 api_key=os.getenv("DEEPGRAM_API_KEY"),
56 model="nova-2"
57 )
58
59 tts = CartesiTTSService(
60 api_key=os.getenv("CARTESI_API_KEY"),
61 voice="samantha"
62 )
63
64 # Create pipeline
65 pipeline = Pipeline([
66 stt,
67 llm,
68 tts,
69 transport.output()
70 ])
71
72 # Enable tracing in your PipelineTask
73 task = PipelineTask(
74 pipeline,
75 params=PipelineParams(
76 allow_interruptions=True,
77 enable_metrics=True, # Required for some service metrics
78 ),
79 enable_tracing=True, # Enables both turn and conversation tracing
80 conversation_id="customer-123", # Optional - will auto-generate if not provided
81 )
82
83 # Run the pipeline
84 runner = PipelineRunner()
85 await runner.run(task)
86
87if __name__ == "__main__":
88 import asyncio
89 asyncio.run(main())

Trace Structure

Traces are organized hierarchically in Opik:

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 interactions.

Using with @track decorator

Use the @track decorator to create comprehensive traces when working with your Pipecat voice agents:

1from opik import track
2
3@track
4def process_voice_input(transcription: str, conversation_id: str):
5 """Process voice input and generate response."""
6
7 # Your custom logic here
8 response = f"Hello! I heard you say: {transcription}"
9
10 return {
11 "transcription": transcription,
12 "response": response,
13 "conversation_id": conversation_id,
14 "timestamp": time.time()
15 }
16
17# Use in your Pipecat pipeline
18async def handle_voice_input(frame):
19 if isinstance(frame, TextFrame):
20 result = process_voice_input(frame.text, conversation_id)
21 # Process the result...

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

Results viewing

Once your Pipecat voice agents are traced with Opik, you can view them in the Opik UI. Each conversation will contain:

  • Complete conversation flow with turns and service calls
  • Detailed service metrics and performance data
  • Token usage and cost tracking for LLM services
  • Audio processing metrics for TTS and STT services
  • Real-time conversation monitoring

Feedback Scores and Evaluation

Once your Pipecat voice agents are traced with Opik, you can evaluate your voice AI applications using Opik’s evaluation framework:

1from opik.evaluation import evaluate
2from opik.evaluation.metrics import Hallucination
3
4# Define your evaluation task
5def evaluation_task(x):
6 return {
7 "message": x["transcription"],
8 "output": x["response"],
9 "reference": x["expected_response"]
10 }
11
12# Create the Hallucination metric
13hallucination_metric = Hallucination()
14
15# Run the evaluation
16evaluation_results = evaluate(
17 experiment_name="pipecat-voice-agent-evaluation",
18 dataset=conversation_data,
19 task=evaluation_task,
20 scoring_metrics=[hallucination_metric],
21)

Advanced Configuration

Custom Service Tracing

You can add custom tracing to your Pipecat services:

1from opentelemetry import trace
2from opentelemetry.trace import Status, StatusCode
3
4tracer = trace.get_tracer(__name__)
5
6class CustomVoiceService:
7 @tracer.start_as_current_span("custom_voice_processing")
8 async def process_audio(self, audio_data):
9 with tracer.start_as_current_span("audio_analysis") as span:
10 # Your custom processing logic
11 span.set_attribute("audio.duration", len(audio_data))
12 span.set_attribute("audio.format", "wav")
13
14 result = await self.analyze_audio(audio_data)
15
16 span.set_attribute("analysis.confidence", result.confidence)
17 span.set_status(Status(StatusCode.OK))
18
19 return result

Conversation Context Tracking

Track conversation context across turns:

1from opik import track
2
3@track
4def maintain_conversation_context(transcription: str, context: dict):
5 """Maintain conversation context across turns."""
6
7 # Update context with new information
8 context["last_user_input"] = transcription
9 context["turn_count"] = context.get("turn_count", 0) + 1
10
11 # Generate contextual response
12 response = generate_contextual_response(transcription, context)
13
14 return {
15 "response": response,
16 "updated_context": context,
17 "turn_number": context["turn_count"]
18 }

Environment Variables

Make sure to set the following environment variables:

$# Pipecat Service Configuration
>export OPENAI_API_KEY="your-openai-api-key"
>export DEEPGRAM_API_KEY="your-deepgram-api-key"
>export CARTESI_API_KEY="your-cartesi-api-key"
>
># Opik Configuration
>export OPIK_PROJECT_NAME="your-project-name"
>export OPIK_WORKSPACE="your-workspace-name"
>
># OpenTelemetry Configuration
>export ENABLE_TRACING="true"
>export OTEL_EXPORTER_OTLP_ENDPOINT="https://www.comet.com/opik/api/v1/private/otel"
>export OTEL_EXPORTER_OTLP_HEADERS="Authorization=<your-opik-api-key>,Comet-Workspace=default"

Troubleshooting

Common Issues

  1. No Traces in Opik: Ensure that your credentials are correct and follow the troubleshooting guide
  2. Missing Metrics: Check that enable_metrics=True in PipelineParams
  3. Connection Errors: Verify network connectivity to Opik
  4. Exporter Issues: Try the Console exporter (OTEL_CONSOLE_EXPORT=true) to verify tracing works
  5. Service Not Found: Ensure all required services (STT, LLM, TTS) are properly configured

Getting Help

Next Steps

Once you have Pipecat integrated with Opik, you can: