Video tutorial
Prerequisites
- An active Tuner account
- A Tuner agent with provider Pipecat
- A Tuner API key, your workspace ID and the agent’s Agent Remote ID. See API keys.
- Python 3.11 to 3.13 (3.14 is not yet supported due to Pipecat dependencies)
- A Python project running pipecat-ai v1.0.0 or later
Overview
tuner-pipecat-sdk is an observer that captures latency signals, transcript segments, and usage metadata from your Pipecat pipeline, then sends a structuredCallPayload to Tuner when the call ends. You don’t make any API calls yourself. If your agent’s LLM step is a LangChain runnable or LangGraph graph, the same observer also captures node transitions, tool calls, and token usage from that layer. See LangChain and LangGraph observability below.
Install the SDK
Pass your credentials
Add the observer
Enable simulation
Step 1: Install the SDK
pipecat-ai>=1.0.0. Do not use Python 3.14: Pipecat dependencies (onnxruntime, numba) do not yet have 3.14 wheels.
Optional extras:
Step 2: Pass your credentials
TheObserver does not read environment variables. Pass the credentials as constructor arguments. You can load them from your own environment variables, as below.
Step 3: Add the observer
Create anObserver instance and attach turn tracking:
Observer is a pipeline-level observer. Register it, its latency_observer and the turn tracker in observers=[...] on the PipelineTask, not as a processor inside Pipeline([...]):
enable_metrics and enable_usage_metrics, the observer logs warnings and LLM/TTS metric fields are absent from the payload.
PipelineWorker replaces PipelineTask. The examples on this page use PipelineTask.EndFrame or CancelFrame, the observer sends the call to Tuner in the background. If the request fails, the SDK logs the failure and never raises or blocks your pipeline. If a call doesn’t show up in Tuner, check your logs for [tuner] failed to deliver call.
For more examples, see the tuner-pipecat-sdk-python examples.
Enable simulation
Required for Call Simulation. Skip it otherwise.Inbound
Tuner calls your agent over SIP.Add your SIP URI in Tuner
Forward the SIP data from your webhook
- Twilio
- Telnyx
<Parameter> tags, so use your own webhook.Attach the SIP data in your bot
call_data from Pipecat’s parse_telephony_websocket also works. On Telnyx, pass the raw start message, because parse_telephony_websocket drops its custom_parameters.SipCallId and X-Correlation-Id. Telnyx’s call.initiated event has no SIP Call-ID, so X-Correlation-Id links a Telnyx call. Tuner links the call on either one. You can call attach_sip more than once. Headers merge, and the first non-empty value wins.
Plivo, Exotel, Jambonz, Daily or your own SIP trunk
Plivo, Exotel, Jambonz, Daily or your own SIP trunk
How the SIP data reaches your bot
How the SIP data reaches your bot
Support another carrier
Support another carrier
name and extract(payload) -> SipInfo. Add forward_to_websocket(info, ws_url) -> Forward to support forwarding.Older SDK versions
Older SDK versions
Outbound
Your agent calls a Simulated Caller at a SIP URI that Tuner sends to your trigger endpoint.- Configure the trigger endpoint in Agent Settings > Simulation Setup. See Set up outbound simulation.
- Report the SIP URI your agent dialed as
recipient, exactly as Tuner sent it. Reading it from the stream needstuner-pipecat-sdk0.2.9 or later.
start message.
- Twilio
- Telnyx
Check simulation works
Start a simulation run. See Run a simulation. When the call ends, check its result in the run. If it shows Unreported, Tuner never received a matching call from your agent. See Fix an Unreported run.End-of-utterance (EOU) delay
Wire your user context aggregator to the observer to capture how long the pipeline took to decide the user was done talking: the gap between the user going silent and the turn closing. This appears on every user turn in the transcript view aseou_delay, eou_confidence, and eou_reason.
eou_reason tells you which signal closed the turn, so eou_delay means something different depending on the value:
LangChain and LangGraph observability
If you use LangGraph or LangChain for your LLM step, the observer can capture node transitions, tool calls, and token usage from inside that runnable alongside the standard call data. Install thelangchain extra and see LangChain / LangGraph.
Configuration options
Call type
Call type
"web_call"):Recording URL
Recording URL
"pipecat://no-recording":https:// link. Tuner stores the default or any other value as sent, but treats the call as having no recording: it has no playback in call details and can’t be added to a Dataset.Disconnection reason
Disconnection reason
disconnection_reason_resolver callable. The resolver is called at flush time and should return a string or None.Use the built-in constants from DisconnectReason or pass a custom string:Model names
Model names
Extra metadata
Extra metadata
Agent version
Agent version
APP_VERSION in your environment:APP_VERSION is not set, the observer reads GITHUB_RUN_NUMBER, CIRCLE_BUILD_NUM or BUILD_NUMBER. The value must be an integer. The constructor argument takes priority over all of them:Trace forwarding
Trace forwarding
traces extra installed, the observer forwards Pipecat’s OpenTelemetry spans to Tuner. forward_traces defaults to True. To turn it off:Debug mode
Debug mode
Cost calculation
Cost calculation
CallUsage) and returns the call cost in USD cents. Implement the method that matches your pricing plan; the snippet below is illustrative.stt_audio_seconds is the call’s wall-clock duration in seconds, used as a proxy for STT duration.Full example
OpenTelemetry traces
Pipecat emits OpenTelemetry spans for every conversation when tracing is on. The SDK forwards them to Tuner, and they appear as a span tree on the call’s Traces tab. See Traces for how to read one.tuner-pipecat-sdk 0.2.8 or later.Install the tracing extras
traces extra, trace forwarding is skipped with a debug log, and the rest of the observer works as usual.Turn on tracing in Pipecat
enable_tracing=True on your PipelineTask. This is Pipecat’s own switch for emitting spans. The SDK can’t set it for you, because you create the task after the observer.Keep forward_traces on
forward_traces defaults to True on the Observer. The SDK sends spans to Tuner with the API key and base URL you passed to the Observer, and tags every span with your call_id. You don’t need setup_tracing(...), a TracerProvider, an exporter, or any OTEL_* environment variable.If you already call Pipecat’s setup_tracing(...) to export traces elsewhere, the SDK adds Tuner as an extra destination. If you configure an exporter yourself, use the OTLP HTTP exporter: Tuner does not accept gRPC.To stop forwarding traces, pass forward_traces=False. Pipecat’s enable_tracing is a separate switch that controls whether Pipecat produces spans at all.Check that it worked
Span reference
The span names come from Pipecat, so they are the same ones you would see in any other OpenTelemetry backend. Service spans nest under turns, under one conversation span:llm span with llm_setup, llm_response, and llm_tool_call or llm_tool_result.
See Pipecat’s OpenTelemetry documentation for the full set, and Traces for how to read the tree in Tuner.
Webhooks
Tuner can notify your systems when it has something to report on a call. See Webhooks.Before you finish
- A test call appears in Call Logs.
- Your API key, workspace ID and Agent Remote ID come from API keys.
- If you use Call Simulation: Enable simulation is done for your agent’s call direction, and one simulated call shows a result other than Unreported.
Troubleshooting
No matching distribution found for onnxruntime
No matching distribution found for onnxruntime
onnxruntime versions that have no 3.14 wheels. Switch to Python 3.12 or 3.13 and create a new venv.Failed to build numba / Cannot install on Python 3.14
Failed to build numba / Cannot install on Python 3.14
Calls don't appear in Tuner
Calls don't appear in Tuner
- Verify that
agent_idis the Agent Remote ID from Agent Settings > Agent Connection (not your agent’s display name). - Confirm
workspace_idis correct. - Ensure
enable_metrics=Trueandenable_usage_metrics=Trueare set onPipelineParams. - Check your application logs for
[tuner] failed to deliver call.
Simulated calls show as Unreported
Simulated calls show as Unreported
sip_call_idis the TwilioCA…CallSid: your TwiML had noSipCallIdparameter. Returnforward_to_websocket(...).twimlfrom your webhook.- No
X-Correlation-Idon a Telnyx call: the stream started withoutcustom_parameters. Sendfwd.streamas thestreaming_startbody. sip_call_idisnull:attach_sipnever ran. Call it with the WebSocketstartmessage.ValueError: Unknown provider: the name is misspelled. Use a built-in name orregister_provider.- See Fix an Unreported run.
wrap_graph / wrap_chain raises ImportError
wrap_graph / wrap_chain raises ImportError
langchain extra isn’t installed. Run pip install 'tuner-pipecat-sdk[langchain]'.The Traces tab never appears
The Traces tab never appears
enable_tracing=Trueis missing on thePipelineTask. Pipecat emits no spans without it.- The
tracesextra isn’t installed. Installtuner-pipecat-sdk[traces]andpipecat-ai[tracing]. forward_traces=Falseis set on theObserver.- The API key is wrong or revoked. Tuner rejects the spans with
401or403.