voice.calls / voice.agents) originates,
transfers, and hangs up calls, and binds server-side agents over the
control-plane API. The data plane (voice.audio_bridge) streams call
audio in and out over our QUIC/MoQT transport. Use it when the call driver
lives on a server rather than in a browser — an outbound dialer, an agent
supervisor, or a “tap the audio to my own ASR” pipeline.
The control plane is pure Python (standard-library HTTP, no native
dependency). The data plane (
voice.audio_bridge) uses our QUIC/MoQT
transport through a shared native library. To publish or subscribe to audio,
the MoQT FFI must be available at runtime (see Install).
The SDK is synchronous and blocking. It does not use asyncio. Uplink
frames arrive on a callback you register.Install and authenticate
1
Install the package
2
Provide the audio transport library (data plane only)
Originating and controlling calls works with the package alone. To stream
audio through
voice.audio_bridge, point the SDK at the native MoQT
transport library and export your API key:3
Construct the client
Voice(...)
Top-level client. All constructor arguments are keyword-only.
str
required
Control-plane API base URL for your workspace, for example
https://engine.clutchcall.dev.str
required
Voice API key (sent as a bearer token). Keep it server-side.
str
required
Your workspace / organization id. It scopes every request.
str
default:"relay.clutchcall.dev"
MoQT relay host the audio bridge dials for the data plane. Override only for
self-hosted / on-prem deployments.
Every surface raises
VoiceError (importable from clutchcall.voice) on a
bad argument or a non-2xx control-plane response.
Originate and control calls
v.calls.originate(...)
Places an outbound call against a trunk and returns a Call. Arguments are
keyword-only.
str
required
Destination in E.164, e.g.
"+15551234567".str
required
Caller-ID in E.164. (The name is
from_ because from is a Python keyword.
The SDK sends it as from on the wire.)str
required
The SIP trunk to originate on. See
SIP trunking.
str | None
default:"None"
If set, the engine binds this server-side agent and wires the audio bridge
end-to-end. You do not need to open an
AudioBridge yourself.int
default:"30"
The number of seconds to ring before the attempt stops.
The Call object
originate and get return a Call. Its sid is the universal key. The same
call_sid names the SIP dialog, the media session, the agent session, the MoQT
namespace, and the CDR.
str
Call identifier (
call_sid).str
One of
dialing, ringing, in_progress, completed, failed, no_answer.str
Destination E.164.
str
Caller-ID E.164.
str | None
Originating trunk.
str | None
Bound agent, if any.
v.agents.attach(call_sid, agent)
Bind a running server-side agent to an existing call. The engine wires the
audio bridge for you. Use this when the call already exists (for example, an
inbound call) and you want the agent runtime to take the audio.
Bridge call audio
voice.audio_bridge.attach(...) opens a bidirectional audio bridge for one
call. It subscribes to the caller’s uplink (voice/<sid>/uplink) and
delivers each frame to your on_uplink callback. It also publishes your
downlink (voice/<sid>/downlink) back toward the caller through
bridge.publish_downlink(...). This is the server / agent side of the bridge:
you receive caller audio and send audio to the caller.
str
required
The
call.sid to bridge.Callable[[bytes, int], None]
required
The SDK calls this for every caller frame with
(frame_bytes, timestamp_us).
It runs on the transport’s delivery thread. Keep it fast and hand off heavy
work."opus" | "pcm16" | "g711_ulaw" | "g711_alaw"
default:"\"opus\""
Wire codec for the downlink you publish. See Codecs.
int
default:"48000"
Sample rate of the audio you publish (48 kHz for Opus).
int
default:"1"
Channel count (mono).
int
default:"20"
Frame duration in ms.
AudioBridge.publish_downlink(frame, *, timestamp_us=None) sends one frame
toward the caller. If you omit timestamp_us, the SDK stamps it from a
monotonic clock. Hold the AudioBridge reference for the call’s lifetime. If
the garbage collector collects it, the session closes.
The Python data plane today ships the server/agent-side attach only
(subscribe uplink, publish downlink). The caller-side helpers exposed by the
TypeScript SDK —
attachCaller, publishUplink, onDownlink — are not yet
part of the Python surface. If you need to originate audio as the caller
from Python (for example, a synthetic caller), use the
TypeScript SDK for now.Codecs and audio format
codec accepts "opus" | "pcm16" | "g711_ulaw" | "g711_alaw". Voice is
audio-only. There are no video codecs. Phone legs are G.711 (µ-law / A-law) on
the wire. Browser and app legs are Opus (48 kHz mono, 20 ms frames). The engine
transcodes to and from its internal PCM representation, so you publish and
receive in the codec you pass to attach. For the full track / namespace model
see
Sessions, calls, tracks & streams.
Full example: originate, attach, tap
Originate a call, let a server-side agent run the ASR/LLM/TTS loop, and tap the uplink in parallel to write a transcript-friendly frame log.This mirrors the
voice_agent_attach.py example shipped with the SDK.
Because the SDK is blocking, run long-lived taps under a thread or process
you control. Drive shutdown from a signal, as above.Related
TypeScript SDK
The primary SDK, including the caller-side audio surface.
Agent control events
The human-agent control channel and its event model.
Calls API
The control-plane call routes the SDK wraps.
Outbound call cookbook
An end-to-end outbound walkthrough.
Stream to your ASR
Tap the uplink into your own speech pipeline.
Agent runtime
What a bound server-side agent does with the audio.

