:443 plane.
What you’re building
Pipecat and ClutchCall sit at different layers. That is why they compose cleanly. Pipecat owns the conversation: the frame pipeline, turn-taking, and your model choices. ClutchCall owns the transport and telephony: the SIP gateway/B2BUA that terminates the carrier trunk, and the media plane that carries the audio over QUIC. The seam between them is a pair of tracks keyed by the call id: an uplink (caller → bot) and a downlink (bot → caller):AudioBridge calls are stock SDK. Everything between them is your
Pipecat pipeline. The pipeline is unchanged from any other Pipecat deployment.
Build the app
1
Take the call and attach the audio bridge
Skip
agents.attach (that call runs our managed runtime). Open the
bridge yourself. Ask for pcm16 at 16 kHz. That is the shape most frame
pipelines expect. The bridge transcodes the PSTN (G.711) leg and the
runtime’s 8 kHz bus for you in both directions.- TypeScript
- Python
2
Wrap the two hooks as a Pipecat transport
Pipecat’s
Transport seam needs exactly two things: a producer of input
audio frames and a consumer of output audio frames. The bridge already
gives you both. onUplink is the producer. publishDownlink is the
consumer. Wrap them so that the rest of the pipeline runs unchanged.Illustrative — you own this class today. The transport below is
your glue code around the real audio bridge, not an installable
package. Class and frame names track Pipecat’s public shape. When you
write this class for real, pin your Pipecat version and match its exact
transport base classes.
3
Assemble the pipeline
Drop the two wrappers on the ends of an ordinary Pipecat pipeline. The STT,
LLM, and TTS processors are stock Pipecat. Pick the providers that you
already use.
4
Run the call, then tear down cleanly
Run the pipeline for the life of the call. When the conversation ends,
close the bridge before you hang up. Both tracks then tear down
cleanly.
- TypeScript
- Python
Where this is headed
A first-class integration would collapse the two wrapper classes above into a single PipecatTransport. That transport would bind directly to our
media-over-QUIC primitives. You would construct it with the call id. You would
drop transport.input() / transport.output() onto the pipeline. You would
write no onUplink/publishDownlink glue.
Design sketch — not shipped.
QuicMoqtTransport does not exist as a
package. It shows the intended shape of a future adapter only.- resample between Pipecat’s frame rate and the runtime’s 8 kHz PCM16 audio bus,
- keep the room-scoped MoQT namespaces valid, and
- carry Opus rather than PCM on browser legs.
Other on-ramps that ship today
If you do not want to write even the wrapper, two seams already let a Pipecat bot take live calls:- WebSocket audio on-ramp
- Vendor bridge (if Pipecat fronts a backend)
Pipecat already speaks WebSocket audio. ClutchCall accepts a bespoke
WebSocket audio sender as a media leg. Point Pipecat’s WebSocket server
transport at that on-ramp. Route the trunk’s inbound rule to your endpoint.
The SIP gateway terminates the carrier while Pipecat drives the
conversation, with no ClutchCall code in the bot. This is the same
path as
migrating a custom WebSocket audio sender.
Related
Pipecat + Transport
The full conceptual framing and the on-ramps that ship today.
Bridge a Pipecat Agent
The single-snippet version of the audio-bridge seam that this recipe uses.
LiveKit Agent with ClutchCall Transport
The sibling recipe for a LiveKit agent over the same transport.
Keep Your Existing Runtime
Adopt only the transport and keep your own agent loop.

