call_sid addresses the call, so recordings, reports, and QoS keyed on it stay
intact across the handoff.
This recipe wires the full path:
Route the number to an AI agent
Inbound calls on your DID land on a server-side agent — no code in your
process answers the phone.
Give the agent a tool to resolve the query
A custom HTTP tool (
lookup_order) lets the model read your systems and
answer for real.Escalate to a human with context
The built-in
route_to_skill tool drops the live caller into an ACD skill
queue with a one-line summary screen-pop. The runtime stamps the call_sid
onto the handoff.The agent runs server-side, inside TeleQuick Voice. You configure it and
its tools once; you don’t hold an audio bridge in your process for this pattern.
Your code shows up in two places only: the backend your
lookup_order tool
calls, and (optionally) the control-plane calls that observe or steer the call.1. Route the number to an AI agent
Inbound routing is control-plane configuration, not SDK code: a DID (or a whole trunk) binds to anagent_id, and calls that land on it inherit that agent. Set
this on the number in the console, or provision it when you buy the number — see
Inbound calls and
Number provisioning.
Once the DID points at your agent, an inbound call is answered by the engine
(early-media SDP, then a 200), the audio bridge is wired end-to-end, and the
agent starts talking. Nothing in your process has to be online for the call to
be answered.
2. Define the agent and its resolve-the-query tool
An agent is a small orchestration graph (its DAG). It has a system prompt, a speech pipeline, and a set of tools the model may call mid-conversation. Author it in the console or push it over the control-plane API — there is no SDK wrapper for the DAG itself (see Agent DAGs and Tool calling). Here the agent is a single streaming (speech-to-speech) node with one custom tool,lookup_order, plus the implicit call-control toolset every voice agent
gets for free:
Agent config (support-bot)
lookup_order tool is an HTTP tool: you declare its name, description,
and an OpenAPI-style parameter schema, and point it at an endpoint you host. The
model fills the parameters; the runtime makes the request and feeds the JSON
response back into the turn.
Tool: lookup_order (http)
- TypeScript
- Python
3. Escalate to a human — with context
You do not author the escalation tool.route_to_skill is part of the
implicit call-control toolset every voice agent carries. Unlike a blind SIP
transfer that hands the caller away, it keeps the caller on our leg, pauses the
AI’s audio, plays hold music, and drops the caller into the ACD ring for a
skill. When a human answers, the caller is bridged.
The model calls it with two fields:
The department to queue to, e.g.
SUPPORT, BILLING, HC_TRIAGE. Match the
department the caller asked for.A one-line reason the caller needs a human. This is the screen-pop the
receiving agent sees before they take the call.
POST https://engine.telequick.dev/api/acd/queue (emitted by the runtime)
SUPPORT skill (or queues the
request if none is online) and returns the chosen agent so the model can say
“connecting you to Ashwin now.” The source_call_id is the same call_sid the
AI leg has been using; the summary becomes the human’s screen-pop.
Accepting the offer
When the offer rings on a human agent’s desktop, the desktop confirms it by hitting the accept endpoint. That clears the offer marker, stops the ring, and bridges the caller — on the samecall_sid:
- TypeScript
- Python
The context that survives the handoff today is the one-line
summary
screen-pop, plus the skill, the caller’s number, and the preserved call_sid.
A richer structured payload — full transcript, verified identity, collected
fields rendered as a screen-pop card — is a product-level capability on the
roadmap, not something the SDK ships wired yet. Build the human-facing card off
the summary + source_call_id for now.4. The sid is the throughline
Becauseroute_to_skill keeps the caller on our leg, the call_sid is stable
from the first ring through the human conversation. That means your control-plane
code can observe or steer the same call at any point with the TeleQuick Voice
SDK:
- TypeScript
- Python
- Model-driven (
route_to_skill) — the agent decides, mid-conversation, that it needs a human and queues to a skill with a summary. Best when the AI owns the judgment call. - App-driven (
call.transfer) — your backend decides and either re-attaches the call to a different agent or REFERs it to a phone number. Best when an external signal (a supervisor, a business rule) forces the handoff.
call_sid is unchanged, so the recording (both legs), the
segmented call report (AI segment vs human segment), and the per-call QoS all
stay keyed to one call.
Related
AI ↔ human handoff
How the live audio actually moves from the AI leg to the human.
Tool calling
HTTP, MCP, client, and the built-in telephony tools in full.
PBX & ACD
Skills, VDNs, and the picker that chooses the human.
Handoffs
The concept model behind AI→human, transfer, and re-attach.
Transfer to a human
The one-call transfer snippet, on its own.
Outbound sales agent
The outbound sibling of this recipe.