Give your voice agent the ability to act during a live call — look up an order, check an appointment slot, file a ticket, fetch a balance — without rebuilding the runtime. You declare a set of tools on the agent; the model sees each tool’s name, description, and argument schema, decides when to call one, and TeleQuick Voice executes it and feeds the result back so the model can keep talking. This is the same tool model the Agent DAG uses under the hood — an llm (or realtime) node advertises tools by name, and the runtime resolves and runs them. Here you configure the tools themselves.

How a tool call flows through a turn

1

Advertise

On the first audio frame of a new session, the runtime hydrates the agent’s tool list and advertises each tool’s name, description, and parameter schema to the model.
2

Call

The model emits a structured tool_call with JSON arguments. The runtime validates those arguments against the tool’s JSON Schema before dispatch, so a malformed call fails fast instead of hitting your endpoint.
3

Execute

The runtime runs the tool — an outbound HTTP request, an MCP tools/call, or a push to your SDK — and captures the result as a JSON string.
4

Feed back

The result returns to the model as a tool_result. The model reasons over it and either answers the caller or calls another tool. Mark a tool silent to hand the result back without prompting a new spoken response.
Tool invokes are synchronous within the model turn. A slow upstream eats the turn budget and the caller hears dead air. Keep each tool fast (sub-second is ideal), and chain multiple short LLM turns rather than cascading several tool calls inside one turn.

Where tools live

Tools are declared on the agent, not baked into the runtime. The control plane persists them under the agent’s config (agent:<agent_id>:config.tools[]) and the runtime hydrates them per session, so edits in the agent console apply to the next call with no redeploy. Each session builds its tool set by unioning your operator-defined tools with a built-in telephony toolset the runtime advertises automatically (transfer, hold/unhold, DTMF, disconnect, supervisor request, and so on — see below and AI ↔ human handoffs). On a name collision the operator tool wins, so declaring a tool named transfer_call overrides the built-in.
A tool whose spec fails to parse is skipped at registration rather than registered broken — so a typo in one tool’s spec can’t shadow a built-in of the same name or wedge the session. Check the agent console’s validation banner if a tool you expected never reaches the model.

Built-in telephony tools

Every session ships with a built-in telephony toolset the model can call with no operator config — these drive the live call itself: move the caller, place them on hold, dial a human, hang up, punch DTMF into a downstream IVR, pull in a supervisor. They are the same operations exposed to ISV apps as CSTA verbs on CTI call-control; here they are tools the LLM calls itself, mid-conversation, when it decides a human or a different destination should take over.
Every transfer passes the realm’s transfer-rule policy. If a destination is disallowed (e.g. a blocked cross-realm hop) the tool returns a structured error instead of connecting, so the model can react in-turn — apologize, try route_to_skill, or read the reason back to the caller — rather than silently failing.

Picking a transfer style

The model has three ways to hand a caller off. The right one depends on whether a human needs to be briefed, and whether the caller should hear that brief.
StyleTool(s)Does the AI stay?Does the caller hear the brief?Reach for it when
Blindtransfer_callNo — leaves at onceNo brief happensYou already know the exact destination and no handoff briefing is needed.
Warm / attendedwarm_transfercomplete_transferYes, until it steps outYes — everyone is in one conferenceYou want to brief the human out loud, with the caller present, before dropping.
Private consultconsultconsult_transfer | consult_cancelYes, speaking privatelyNo — caller is on holdYou need to check with a third party privately and may decide not to transfer.

Blind transfer — transfer_call

A one-step blind transfer (SIP REFER). The runtime hands the caller to the destination and the AI leaves the call immediately — there is no briefing phase. Use it when the destination is known and no context needs to be passed by voice.
destination
string
required
Where to send the caller. Accepts an E.164 number (+15551234567), a SIP URI (sip:queue@pbx.example.com), or a tel: URI.
referred_by
string
Optional Referred-By identity presented on the REFER. Defaults to the trunk’s identity when omitted.

Warm transfer — warm_transfer then complete_transfer

An attended transfer where the caller hears the handoff. The AI dials the destination and joins everyone into a conference so it can speak the brief; the caller is live throughout and hears the whole exchange.
1

warm_transfer { destination }

The AI dials destination and joins a conference with the caller. All three parties are connected — the AI delivers the handoff brief out loud while the caller listens.
destination
string
required
A skill name, extension, SIP URI, or PSTN number (E.164) to bring into the conference.
2

complete_transfer { }

Once the brief is done, the AI steps out of the conference. The caller and the destination stay connected; only the AI leg stops. No parameters.

Private consult — consult then consult_transfer or consult_cancel

An attended, one-to-one consult where the caller does not hear anything. The AI dials a third party and speaks privately while the caller waits on hold — then it either connects them or returns to the caller.
1

consult { destination }

The caller is effectively placed on hold and the AI dials destination on a private leg. The AI and the consulted party can talk without the caller hearing.
destination
string
required
A skill name, extension, SIP URI, or PSTN number (E.164) to consult privately.
2

Then resolve it one of two ways

Connects the caller to the consulted party and the AI drops out — the two parties are left talking. No parameters.

The rest of the toolset

The remaining built-in tools control the caller’s own leg or pull in a human, and take effect the moment the model calls them.
ToolParamsWhat it does
route_to_skillskill?Queues the caller to a human skill / queue (ACD) and the AI steps out. Use for “get me a human” when there’s no specific number. Omit skill to use the agent’s default queue.
hold_callPlaces the caller on hold (they hear the trunk’s hold treatment).
unhold_callTakes the caller back off hold.
disconnect_callreason?Hangs up the call. reason is recorded on the CDR.
send_dtmfdigit (0-9*#A-D), duration_ms? (default 100), mode (rfc2833 | inband)Punches a DTMF digit down the line to navigate a downstream IVR.
request_supervisorreason, urgency (low | medium | high)Signals a supervisor to join / assist without transferring the caller away.
Any of these can be overridden by declaring an operator tool of the same name (the operator tool wins the union), or pulled from a tenant entirely — see Hiding tools per tenant below.

Per-tool spec

Every entry in tools[] shares the same envelope; the kind-specific fields go inside spec:
kind
string
required
http, mcp, or client. Selects which executor runs the tool.
name
string
required
Unique within the agent. This is the function name the model sees and calls.
description
string
required
Human-readable purpose, advertised to the model. Write it for the model — it’s the primary signal for when to call the tool.
silent
boolean
default:"false"
When true, the tool result is handed back without asking the model to generate a fresh spoken turn — useful for fire-and-forget side effects (logging a disposition, tagging the call) where you don’t want the agent to narrate the action.
spec
object
required
Kind-specific configuration. Every kind accepts a parameters field — a standard JSON Schema for the tool’s arguments. If you omit it on an http tool, the runtime synthesizes one from the {{placeholder}} tokens in your URL and body.

Tool kinds

KindStatusWhat it does
httpshippedCalls an HTTP(S) endpoint you own. URL, headers, and body templates substitute {{argument}} from the model’s tool arguments. Auth: bearer, basic, or custom header. 10s default timeout.
mcpshippedJSON-RPC 2.0 tools/call against a remote MCP server over Streamable HTTP. Each tool is declared explicitly (no tools/list auto-discovery yet). Same auth shapes as http.
clientscaffoldedThe tool is advertised and the call is parsed, but the runtime pushes it to your SDK to fulfil. See the status note below.
{
  "kind": "http",
  "name": "lookup_order",
  "description": "Look up an order by its ID and return its status.",
  "silent": false,
  "spec": {
    "method": "GET",
    "url": "https://api.example.com/orders/{{order_id}}",
    "headers": { "X-Tenant": "acme" },
    "auth": { "type": "bearer", "token": "sk_live_..." },
    "parameters": {
      "type": "object",
      "properties": {
        "order_id": { "type": "string", "description": "Order id to look up." }
      },
      "required": ["order_id"]
    },
    "timeout_ms": 10000
  }
}
{{name}} tokens in url, headers, and body are replaced with the matching top-level property from the model’s arguments. URL substitutions are percent-encoded; body substitutions are inserted verbatim, so write JSON in the body template if your endpoint expects JSON. auth accepts { "type": "bearer", "token": ... }, { "type": "basic", "user": ..., "pass": ... }, or { "type": "header", "name": ..., "value": ... }. The response body is returned to the model as the tool result.

Hiding tools per tenant

To pull a built-in telephony tool out of a tenant’s agents without editing each agent, write the tool names as a JSON array to TeleQuick:tenant:<tenant_id>:telephony_disabled_tools. Disabled tools are filtered out before the tool set reaches the model, and re-checked at invoke time so a stale provider session can’t slip a call through for a name you disabled mid-call.

Native tools

For tools that need privileged access to the live call — realm-policy evaluation, telephony dispatch, recording control, supervisor signalling — the built-in telephony toolset is implemented as first-class runtime code rather than as http/mcp entries. That path is for platform developers building into the runtime itself; tenants and operators should reach for the http, mcp, and (soon) client kinds above, which need no rebuild.

Runtime overview

How agents, pipelines, and providers fit together.

Session lifecycle

When tools hydrate and how the turn budget is spent.

AI ↔ human handoffs

The built-in transfer / supervisor toolset in context.

CTI call-control verbs

The same operations as CSTA verbs for ISV apps to drive over the CTI leg.

BYO ASR / LLM / TTS

Which providers surface tool calling in a cascaded pipeline.