Skip to main content
a variable is a {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 — get or post; perform runs a built-in performedAction (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 reports hasSecret.
  • timeoutMs — 100–30000, default 5000. waitForResponse — whether a during_call tool blocks the model until the response arrives.
  • llmParams[] — for during_call tools, 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" }. name is a JSON key looked for anywhere in the response; path pins it to one dotted location instead.
tokens are filled, in order of precedence, from the model’s arguments (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 named route_agent to the tool output that holds the agent’s UUID or ua_… handle:
curl
with the tool declaring "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_agent names 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.
next: outbound calls.