{name} in a prompt or greeting with a default value. a
tool is an http endpoint of yours: a before_call tool runs at the start
of every call and fills variables from its response; a during_call tool is
a function the model can invoke mid-conversation. both are account-wide — one
list, shared by every agent.
variables
GET /v1/variables · POST /v1/variables · GET | PATCH | DELETE /v1/variables/{id}
typing {company} into an agent’s prompt declares a variable named company
(blank default) if none exists. declare it yourself to set the default:
string
required
^[A-Za-z][A-Za-z0-9_]*$, up to 64 characters, unique on the account
(case-insensitive).string
used when no tool supplies a value, or the tool fails. up to 2000
characters; blank by default.
string
a
before_call tool whose response fills this variable at the start of each
call.string
which of that tool’s
outputs to take. omit for a tool with one output, or
one named like the variable.string
on a campaign call, take the value from this column of the
person’s row (the header, case-insensitive). an empty cell, and every
other call, use
defaultValue. a variable has a tool or a campaign
column, never both.curl
PATCH takes any subset; "toolId": null disconnects the tool and
"campaignColumn": null the column. setting one source clears the other. DELETE is
refused with 409 agent_variable_in_use while any agent’s live prompt,
greeting or draft still spells {name} — remove it from the prompt first.
up to 200 variables per account.
tools
GET /v1/tools · POST /v1/tools · GET | PATCH | DELETE /v1/tools/{id}
GET /v1/tools returns your tools as items, the platform’s built-ins as
defaults (end_call lets the agent hang up), and contextParams — the
tokens every tool can use: {phone_number} (the other end of the call),
{user_id} (your account), {agent_id} and {call_id} (the call’s id, the
same one POST /v1/calls and GET /v1/calls show). a before-call tool
receives {call_id} when the call starts — for a web call that is inside
POST /v1/webcall, before its response reaches you, so a tool that must look
the call up by id needs the call registered first.
create
string
required
same rules as a variable name. prompts attach the tool as
{{name}}.string
required
what it does. for a
during_call tool this is what the model reads to decide
when to call it — write it for the model.string
required
before_call or during_call.object
required
the http call to make:
action—getorpost;performruns a built-inperformedAction(end_call,transfer_call) instead of an http call.method,url(http(s)://…),headers[],params[],body— any of them may contain{tokens}.auth—{ "type": "none" | "bearer" | "api_key" | "basic", "token", "headerName", "username", "password" }. write-only: the API only ever reportshasSecret.timeoutMs— 100–30000, default 5000.waitForResponse— whether aduring_calltool blocks the model until the response arrives.llmParams[]— forduring_calltools, the arguments the model supplies:{ "name", "type": "string" | "number" | "integer" | "boolean", "description", "required" }. each becomes a{name}token.outputs[]— values the tool exposes:{ "name", "path" }.nameis a JSON key looked for anywhere in the response;pathpins it to one dotted location instead.
llmParams), then the account’s variables, then the context params.
curl
PATCH replaces config whole, except that an auth block without a
token / password keeps the stored credential (an empty string clears it).
DELETE answers 204; variables the tool fed fall back to their defaults.
names must not collide with a built-in (409 agent_tool_name_reserved); up to
50 tools per account.
putting them together
1
a before-call tool fills variables
create
lookup_account as above, then a variable that reads it:
{ "name": "first_name", "toolId": "<tool id>", "toolOutput": "firstName" }.
at the start of every call the tool runs once with the caller’s number and
{first_name} in the prompt and greeting becomes the value it returned —
or the default if it timed out. to key the lookup on {call_id} instead
(a web call has no caller number), register the call first so you hold the
id before the tool is asked about it.2
a during-call tool is a function
create
{ "kind": "during_call", "config": { "action": "post", "url": "https://api.example.com/v1/tickets", "body": "{\"summary\": \"{summary}\"}", "llmParams": [{ "name": "summary", "type": "string", "description": "one line describing the issue", "required": true }] } }
and write {{create_ticket}} in the prompt where you want the agent to use
it. the model decides when to call it and supplies summary.3
built-ins
{{end_call}} in a prompt lets the agent hang up when the conversation is
done. it needs no configuration.headers whose names look like credentials (
authorization, cookie,
anything containing key, token, secret, …) are stripped from
config.headers — put the credential in auth instead, where it is stored
encrypted.route an incoming call to another agent
on an incoming call — to a rented number or through a SIP trunk — a before-call tool can hand the call to another of your agents: one agent per voice or persona, picked per caller. connect a variable namedroute_agent to the tool output that holds the agent’s
UUID or ua_… handle:
curl
"outputs": [{ "name": "agent", "path": "context.agent" }]
and answering, say:
- the number’s agent picks up and its before-call tools run once, as on any call.
- when
route_agentnames another of your agents, that agent takes the call: its prompt, greeting, voice, languages, tools and call settings. its{variables}are filled from the same tool answers — no tool is called twice. - the call shows up under that agent in your calls and usage, at its voice’s rate.
- an empty value, an id that is not one of your agents, a vision agent, an agent never deployed or the number’s own agent leaves the call with the number’s agent.
- no prompt needs to mention
{route_agent}, and the model never sees it. - before-call tools see the number’s agent as
{agent_id}; tools called during the call see the agent that took it. - web calls, outbound calls and campaigns are not routed.
deploy the agents you route to: a routed call runs an agent’s live settings,
not its draft. if the agent’s voice can’t take a phone call on your account,
the call isn’t dropped — it keeps the number’s agent’s voice and settings.