Skip to Content

Pipecat (tracing)

Pipecat  is an open-source framework for building real-time, multimodal AI applications. It provides a pipeline architecture for voice agents, video processing, and other real-time experiences with support for speech-to-text, LLMs, and text-to-speech. Respan gives you full observability over every Pipecat turn, LLM call, STT step, TTS step, and tool execution, and gateway routing through the OpenAI-compatible Respan endpoint.

Set up Respan

Create an account at platform.respan.ai  and grab an API key .

Paste this into your coding agent:

Help me set up Respan tracing with the Pipecat integration. Follow https://www.respan.ai/docs/integrations/pipecat.md

Setup

Install packages

Terminal
pip install respan-ai respan-instrumentation-pipecat

Set environment variables

Terminal
export OPENAI_API_KEY="YOUR_OPENAI_API_KEY" export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"

OPENAI_API_KEY is used by Pipecat’s OpenAI service. RESPAN_API_KEY exports traces to Respan. If you use different Pipecat services, set their provider keys as usual.

Initialize and run

Python
import asyncio import os from dotenv import load_dotenv from pipecat.frames.frames import EndFrame, LLMContextFrame, LLMFullResponseEndFrame, LLMTextFrame from pipecat.pipeline.pipeline import Pipeline from pipecat.pipeline.runner import PipelineRunner from pipecat.pipeline.task import PipelineTask from pipecat.processors.aggregators.llm_context import LLMContext from pipecat.processors.frame_processor import FrameDirection, FrameProcessor from pipecat.services.openai.llm import OpenAILLMService from respan import Respan from respan_instrumentation_pipecat import PipecatInstrumentor load_dotenv() respan = Respan(instrumentations=[PipecatInstrumentor()]) class TextCollector(FrameProcessor): def __init__(self): super().__init__(name="text_collector", enable_direct_mode=True) self.text = [] self.done = asyncio.Event() async def process_frame(self, frame, direction: FrameDirection): await super().process_frame(frame, direction) if isinstance(frame, LLMTextFrame): self.text.append(frame.text) elif isinstance(frame, LLMFullResponseEndFrame): self.done.set() await self.push_frame(frame, direction) async def main(): collector = TextCollector() llm = OpenAILLMService( api_key=os.environ["OPENAI_API_KEY"], settings=OpenAILLMService.Settings(model=os.getenv("OPENAI_MODEL", "gpt-4.1-nano")), ) pipeline = Pipeline([llm, collector]) task = PipelineTask(pipeline, cancel_on_idle_timeout=False, enable_rtvi=False) async def push_frames(): await asyncio.sleep(0.05) context = LLMContext( messages=[{"role": "user", "content": "Reply in one short sentence about Pipecat tracing."}] ) await task.queue_frame(LLMContextFrame(context)) await asyncio.wait_for(collector.done.wait(), timeout=30) await asyncio.sleep(0.2) await task.queue_frame(EndFrame()) await asyncio.gather(PipelineRunner(handle_sigint=False).run(task), push_frames()) print("".join(collector.text)) await asyncio.sleep(1) asyncio.run(main())

View your trace

Open the Traces page  to see your Pipecat turn with child LLM, STT, TTS, and tool spans.

Configuration

ParameterTypeDefaultDescription
api_keystr | NoneNoneFalls back to RESPAN_API_KEY env var.
base_urlstr | NoneNoneFalls back to RESPAN_BASE_URL env var.
instrumentationslist[]Plugin instrumentations to activate (e.g. PipecatInstrumentor()).
customer_identifierstr | NoneNoneDefault customer identifier for all spans.
thread_identifierstr | NoneNoneDefault thread identifier for all spans.
metadatadict | NoneNoneDefault metadata attached to all spans.
environmentstr | NoneNoneEnvironment tag (e.g. "production").

PipecatInstrumentor forwards keyword arguments to the upstream OpenInference Pipecat instrumentor, including options such as debug_log_filename and config.

Attributes

In Respan()

Set defaults at initialization. These apply to all spans.

Python
from respan import Respan from respan_instrumentation_pipecat import PipecatInstrumentor respan = Respan( instrumentations=[PipecatInstrumentor()], customer_identifier="user_123", thread_identifier="session_abc_123", metadata={"service": "voice-agent", "version": "1.0.0"}, )

With propagate_attributes

Override per-request using a context scope.

Python
from respan import Respan, propagate_attributes from respan_instrumentation_pipecat import PipecatInstrumentor respan = Respan(instrumentations=[PipecatInstrumentor()]) async def handle_session(user_id: str): with propagate_attributes( customer_identifier=user_id, thread_identifier="session_abc_123", metadata={"plan": "pro"}, ): await runner.run(task)
AttributeTypeDescription
customer_identifierstrIdentifies the end user in Respan analytics.
thread_identifierstrGroups related messages into a conversation.
metadatadictCustom key-value pairs. Merged with default metadata.

Decorators (optional)

Decorators are not required. Pipecat turns, LLM calls, STT, TTS, and tools are auto-traced by the instrumentor. Use @workflow and @task to add application-level structure around a Pipecat session.

Python
from respan import Respan, workflow, task from respan_instrumentation_pipecat import PipecatInstrumentor respan = Respan(instrumentations=[PipecatInstrumentor()]) @task(name="run_pipecat_task") async def run_pipecat_task(task): await runner.run(task) @workflow(name="voice_session") async def voice_session(task): await run_pipecat_task(task)