Tools, variables and goals

How an agent reaches your systems mid-call, how it knows who it is talking to, and how you find out afterwards whether the call worked.

Variables: what the agent knows before it speaks

Write {{name}} anywhere in the prompt and pass a value for it. This is what lets one saved agent serve every caller instead of needing an agent per person.

"system_prompt": "You are calling {{customer_name}} about order {{order_id}}.",
"variables": { "customer_name": "Asim", "order_id": "ORD-4192" }

Substitution happens per turn, not once per call, so a value a tool discovers mid-conversation is reflected in the prompt from then on.

An unfilled placeholder is left visible, and reportedBlanking it makes the model invent a name to fill the gap, which reads as a hallucination when the real cause is a missing value. You get a variables_missing event instead.

Tools: reaching your systems mid-call

Tools are declared as data on the agent — no code runs on our side beyond the HTTP request you describe. Placeholders in the URL, headers or body are filled from the model's arguments and the call's variables.

"tools": [{
  "name": "check_order",
  "description": "Look up the delivery date for an order id.",
  "url": "https://api.yourcompany.com/orders/{order_id}",
  "method": "GET",
  "headers": { "X-Api-Key": "{{crm_key}}" },
  "parameters": {
    "order_id": { "type": "string", "description": "the order number" }
  },
  "timeout_s": 5
}]

What we do to protect you, and what we cannot

A tool URL is a request made from inside our network, so it is the one place a customer can point us at our own infrastructure. Every major cloud exposes a metadata service on a link-local address that hands out credentials to anything on the machine that asks for them, which makes an unguarded outbound fetch a way to extract them.

GuardWhy
Scheme must be http or httpsfile:// would read the disk
Hostname resolved, every address must be publicly routableBlocks loopback, private, link-local, CGNAT, multicast, and the IPv6 equivalents
Redirects are not followedA permitted host answering 302 to the metadata service would undo the check
Hard timeout, 5s default and 15s ceilingA hanging tool is a caller listening to silence
Response capped at 8KBThe model cannot use more, and a large body is a slow turn
Errors are returned to the model as textYour broken webhook is not our outage — the agent says it could not check and carries on
Residual risk, stated plainly: DNS rebindingWe validate the hostname and then hand the URL to an HTTP client, which resolves it again. A hostname that answers with a public address on the first lookup and a private one on the second defeats the check. Closing it properly means connecting to the validated address with the Host header set, or an egress policy that cannot reach link-local at all. That is infrastructure work and is not done yet.

Extraction: pulling facts out afterwards

"extract": [
  { "name": "agreed_date", "description": "the delivery date the caller accepted", "type": "string" },
  { "name": "phone_number", "description": "a callback number if given", "type": "string" }
]

Runs after the call, not during — mid-call it would cost a round trip the caller waits through and would have to guess from an unfinished conversation. Every field you ask for comes back, with null where the transcript did not support it, because “not asked for” and “asked for and not found” are different answers.

Goals: did the call work?

"goal": "Successful when the caller confirms a delivery date."

Scored against the transcript after the call. The scorer is deliberately hard to please: it demands evidence from the transcript, offers “unclear” as a first-class answer, and defaults to failure. A model asked whether a call went well simply says yes, so an agreeable scorer would report a 100% success rate on any input.

The verdict is stored as achieved, not achieved, or unclear — three states, not two. Collapsing unclear into failure would quietly turn every ambiguous call into a loss in your numbers.

Verified in both directionsA call where the caller said “haan bilkul, mangalwar confirm hai” scored achieved and quoted that line as its evidence. A call where the caller refused scored not achieved. A scorer only tested on successes passes every test and is worthless.

Results land on the call record: see analytics, or open any call in the dashboard.