call.* events on your agent’s webhook or WebSocket. The call’s media, and what the other side is doing, arrive as events on the transport your agent joined the room with.
Receive call events
Every event carries the whole Call object. Keep the snapshot with the highest
revision for each call.id. Answer in the background: the WebSocket acknowledges an event only after your handler returns, and a call lasts minutes.
Follow the call from the transport
The transport emits events as media connects, the other side changes, and the call ends. Pipecat raises the same moments ason_connected, on_first_participant_joined, on_call_state_updated and on_participant_left.
Use your own TURN servers
By default the transport uses the STUN and TURN servers the room sends, which Relay mints for each call. An agent in a container or behind a firewall that blocks UDP connects through TURN with no setup. To use your own servers, passiceServers; yours replace the room’s.
iceServers can also be a function that returns a fresh list before every connection attempt, so short-lived credentials are minted each time. Python uses only the first STUN and the first TURN URL, so a network that blocks all UDP needs a transport=tcp TURN URL first.
Read diagnostics when a call fails
connect() has no overall deadline. A media session that does not connect within 5 seconds, fails, or stays disconnected for 7 seconds is replaced, for as long as the call is ringing or in progress, and each replacement emits restarted. connect() fails only when the call ends or the room closes.
diagnostics() returns what happened, with a one-line summary to log: candidate counts, connection state changes, packets in each direction, and the room frames seen.
silence mean your agent connected but wrote no audio.

