The Python Voice SDK gives your backend two surfaces against TeleQuick Voice: a control plane (voice.calls / voice.agents) that originates, transfers, hangs up, and binds server-side agents over the control-plane API, and a data plane (voice.audio_bridge) that streams call audio in and out over our QUIC/MoQT transport. Reach for it when the call driver lives on a server — an outbound dialer, an agent supervisor, a “tap the audio to my own ASR” pipeline — rather than in a browser.
The control plane is pure Python (standard-library HTTP, no native dependency). The data plane (voice.audio_bridge) rides our QUIC/MoQT transport through a shared native library, so publishing or subscribing to audio needs the MoQT FFI 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

pip install telequick
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:
export CLUTCHCALL_MOQT_FFI=/path/to/libclutchcall_moqt_ffi.so
export TELEQUICK_API_KEY=...   # your Voice API key
Skip the library if you only originate calls and let a server-side agent handle the audio (agent=... on originate, or voice.agents.attach). The engine wires the bridge for you in that case.
3

Construct the client

import os
from telequick.voice import Voice

v = Voice(
    base_url="https://engine.telequick.dev",
    api_key=os.environ["TELEQUICK_API_KEY"],
    org_id="org_abc",
)

Voice(...)

Top-level client. All constructor arguments are keyword-only.
base_url
str
required
Control-plane API base URL for your workspace — e.g. https://engine.telequick.dev.
api_key
str
required
Voice API key (sent as a bearer token). Keep it server-side.
org_id
str
required
Your workspace / organization id. Scopes every request.
relay_host
str
default:"relay.telequick.dev"
MoQT relay host the audio bridge dials for the data plane. Override only for self-hosted / on-prem deployments.
The client exposes three helpers:
AttributeTypePlane
v.callsCallscontrol — originate / get / transfer / hangup
v.audio_bridgeAudioBridgeFactorydata — attach and stream audio
v.agentsAgentscontrol — bind a server-side agent to a call
Every surface raises VoiceError (importable from telequick.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.
to
str
required
Destination in E.164, e.g. "+15551234567".
from_
str
required
Caller-ID in E.164. (Named from_ because from is a Python keyword; it is sent as from on the wire.)
trunk_id
str
required
The SIP trunk to originate on. See SIP trunking.
agent
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.
ring_timeout_sec
int
default:"30"
Seconds to ring before giving up.
call = v.calls.originate(
    to="+15551234567",
    from_="+15558675309",
    trunk_id="trunk_main",
    agent="healthcare-assistant",   # optional: engine drives the audio
    ring_timeout_sec=30,
)
print(call.sid, call.status)

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.
sid
str
Call identifier (call_sid).
status
str
One of dialing, ringing, in_progress, completed, failed, no_answer.
to
str
Destination E.164.
from_
str
Caller-ID E.164.
trunk_id
str | None
Originating trunk.
agent
str | None
Bound agent, if any.
Methods:
# Fetch current state for a known sid
call = v.calls.get(sid="call_...")

# Transfer — pass EXACTLY ONE of to (a PSTN number) or agent (re-attach)
call.transfer(to="+15557654321")
call.transfer(agent="tier2-support")

# End the call
call.hangup()
transfer requires exactly one of to=<E.164> or agent=<id>; passing both or neither raises VoiceError. Peer-initiated transfer over SIP REFER is covered under AI ↔ human handoff.

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 (e.g. inbound) and you want the agent runtime to take the audio.
v.agents.attach(call.sid, "healthcare-assistant")

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, and it publishes your downlink (voice/<sid>/downlink) back toward the caller via bridge.publish_downlink(...). This is the server / agent side of the bridge — you receive caller audio and send audio to the caller.
call_sid
str
required
The call.sid to bridge.
Called for every caller frame with (frame_bytes, timestamp_us). Runs on the transport’s delivery thread — keep it fast and hand off heavy work.
codec
"opus" | "pcm16" | "g711_ulaw" | "g711_alaw"
default:"\"opus\""
Wire codec for the downlink you publish. See Codecs.
sample_rate
int
default:"48000"
Sample rate of the audio you publish (48 kHz for Opus).
channels
int
default:"1"
Channel count (mono).
frame_ms
int
default:"20"
Frame duration in ms.
def on_uplink(frame: bytes, ts_us: int) -> None:
    my_asr.feed(frame)          # caller audio → your pipeline

bridge = v.audio_bridge.attach(call.sid, codec="opus", on_uplink=on_uplink)

# Send audio back to the caller
for opus_frame in my_tts.stream():
    bridge.publish_downlink(opus_frame)

# Release when done — this closes the MoQT session and drops both tracks
bridge.close()
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 — letting it be collected closes the session.
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 (e.g. 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.
import os, signal, struct, threading, time
from telequick.voice import Voice

v = Voice(
    base_url="https://engine.telequick.dev",
    api_key=os.environ["TELEQUICK_API_KEY"],
    org_id="org_abc",
)

# 1. Originate; `agent` lets the engine drive the audio end-to-end.
call = v.calls.originate(
    to="+15551234567", from_="+15558675309",
    trunk_id="trunk_main", agent="healthcare-assistant",
)
print(f"dialing: sid={call.sid}")

# 2. Tap the uplink in parallel — write [u32 len][u64 ts_us] + frame.
out = open("caller.opus", "wb")

def on_uplink(frame: bytes, ts_us: int) -> None:
    out.write(struct.pack("<IQ", len(frame), ts_us))
    out.write(frame)

bridge = v.audio_bridge.attach(call.sid, codec="opus", on_uplink=on_uplink)

# 3. Hold until SIGTERM, then tear down cleanly.
stop = threading.Event()
signal.signal(signal.SIGTERM, lambda *_: stop.set())
try:
    while not stop.is_set():
        stop.wait(timeout=2.0)
finally:
    bridge.close()
    call.hangup()
    out.close()
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 and drive shutdown from a signal, as above.

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.