Installation
Install the required packages:If you plan to use the advanced audio recording features, also install:
pip install scipy numpyQuickstart tutorial
Follow this step-by-step tutorial to create a voice AI agent with Pipecat and LangSmith tracing. You’ll build a complete working example by copying and pasting code snippets.Step 1: Set up your environment
Create a.env file in your project directory:
.env
Step 2: Download the span processor
Pipecat emits OpenTelemetry spans, but its attribute names aren’t ones LangSmith recognizes by default. A custom span processor translates those attributes so your traces render properly in LangSmith. Add the custom span processor file and save it aslangsmith_processor.py in your project directory.
What does the span processor do?
What does the span processor do?
The span processor enriches Pipecat’s OpenTelemetry spans with LangSmith-compatible attributes so your traces display properly in LangSmith.Key functions:
- Converts Pipecat span types (stt, llm, tts, turn, conversation) to LangSmith format.
- Adds
gen_ai.prompt.*andgen_ai.completion.*attributes for message visualization. - Renders the whole-conversation transcript onto the root run.
- Handles audio file attachments (for advanced usage).
Step 3: Create your voice agent file
Create a new file calledagent.py and add the following code. We’ll build it section by section so you can copy and paste each part.
Part 1: Import dependencies
Part 2: Define the main function
Part 3: Add the entry point
Step 4: Run your agent
Run your voice agent:Advanced usage
Trace a nested LangGraph agent
Instead of a stock LLM service, you can use an in-process LangChain or LangGraph agent as the LLM stage of your pipeline. With a few adjustments, the agent’s model and tool runs nest inside Pipecat’sllm span so the whole conversation stays a single trace.
Three things make this work:
- Set
LANGSMITH_TRACING_MODE=otel. This makes the LangSmith SDK emit your LangChain/LangGraph runs as OpenTelemetry spans through the same provider, so they nest under Pipecat’sllmspan instead of forming separate top-level traces. - Use a traced LLM service. A bare
FrameProcessorproduces nollmspan for the graph’s runs to nest under. Subclass a traced service such asOpenAILLMServiceand run your graph from the traced context handler so its runs land inside thellmspan. - Set
llm_span_kind="chain"on the span processor. With the graph nested inside, Pipecat’sllmspan no longer performs the inference itself: the graph’s own model nodes are the real LLM runs. Marking the wrapper achainavoids an LLM run nested inside another LLM run.
Only the final answer is spoken, but the tool-call exchange must be persisted back into Pipecat’s
LLMContext (as OpenAI-format messages) or the model loses its tool history on later turns.Custom metadata and tags
You can add custom metadata to your traces using span attributes:Recording and attaching audio to traces
Record the conversation and attach the audio to the root run so you can listen to it alongside the transcript. For the underlying attachment API, see Upload files with traces. Record what was heard, not what was generated. The naive approach, adding a recordingFrameProcessor to the pipeline, taps the TTS frames upstream of transport.output(), so it over-captures: it includes audio the user never heard when a barge-in truncates the agent mid-sentence. Instead, tap at the device-write boundary, which the output transport reaches only after interruption truncation.
The demo’s RecordingLocalAudioTransport does this: it records played agent audio in write_audio_frame and user audio off the input callback, then writes one stereo WAV (left channel user, right channel agent) using the shared build_stereo_session_wav helper. Use these as a reference implementation and adapt them to your project.
Swap LocalAudioTransport for the recording transport, register the recording with the span processor so it attaches when the conversation span ends, and save it in a finally block:
register_recording accepts any object with a save_recording() method as audio_recorder. The span processor calls it when the conversation span ends, so the file is on disk before it is read and attached. The finally block covers shutdown ordering and the case where tracing is disabled.Troubleshooting
Spans not appearing in LangSmith
If traces aren’t showing up in LangSmith:- Verify environment variables: Ensure
OTEL_EXPORTER_OTLP_ENDPOINTandOTEL_EXPORTER_OTLP_HEADERSare set correctly in your.envfile. - Check API key: Confirm your LangSmith API key has write permissions.
- Verify import: Make sure you’re importing
setup_langsmith_tracingfromlangsmith_processor.pyand calling it before running the pipeline. - Check .env loading: Ensure
load_dotenv()is called before importing Pipecat components.
Messages not showing correctly
If conversation messages aren’t displaying properly:- Check span processor: Verify
langsmith_processor.pyis in your project directory and imported correctly. - Verify conversation ID: Ensure you’re setting a unique
conversation_idinPipelineTask. - Enable turn tracking: Make sure
enable_turn_tracking=Trueis set inPipelineTask.
Audio not working
If your microphone or speakers aren’t working:- Check permissions: Ensure your terminal/IDE has microphone access.
- Test audio devices: Verify your microphone and speakers work in other applications.
- VAD settings: Try adjusting
SileroVADAnalyzer()settings if speech isn’t being detected. - Check services: Ensure OpenAI API key is valid and has access to Whisper and TTS.
Import errors
If you’re getting import errors:- Install dependencies: Run
pip install langsmith "pipecat-ai[whisper,openai,local]" opentelemetry-exporter-otlp python-dotenv. - Check Python version: Ensure you’re using Python 3.9 or higher.
- Verify langsmith_processor: Make sure
langsmith_processor.pyis downloaded and in the same directory as youragent.py.
Performance issues
If responses are slow:- Use faster models: Switch to
gpt-5.4-minifor the LLM (already in the tutorial). - Check network: Ensure stable internet connection for API calls.
- Local STT: Consider using local Whisper instead of API-based services.
Advanced: Audio recording troubleshooting
For issues with the advanced audio recording features, see the complete demo documentation.Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

