{{root.name}} tokens. There are six roots, and
between them they are the whole vocabulary an operation has: what the model
sent, what earlier operations produced, what the session knows, what the
platform knows, what the workspace configured, and your credentials.
The six roots
Every root works in the URL, in the query, in the body and in headers — and
in every other templated string in the tree: a
say, a set_variable value, an
if’s left and right, a frontend_rpc payload.
Three places templates deliberately do not resolve:
- A
codeoperation’s TypeScript. It has no template syntax at all; the same six roots arrive asinput.args,input.tooldataand so on. - An
httpoperation’smethod, which is a fixed choice ofGET,POST,PUT,PATCHorDELETE. - A
transferdestination, which is a literal phone number by design.
"{{args.quantity}}"
sends the number 3, not the string "3"; "{{tooldata.slots}}" sends the
array. Put anything else in the string — a space, a prefix — and the token is
stringified into the surrounding text.
A token whose root is not one of the six is an error at save, not text. A
bare {{name}}, a {{customer.number}} pasted from another platform, or a typo
like {{userdate.name}} is refused when the tool is saved, because the
alternative is sending those braces to your API on every call. There is no
escape syntax; prose containing {{anything}} cannot be saved outside a code
operation.
The two stores
tooldata and userdata are the two places an operation can write. Which one
you pick is not a detail:
tooldata is created empty every time the tool runs and is gone when it
returns. Only later operations in the same tree can read it. It is the
plumbing between two operations.
userdata belongs to the session. Other tools read it, later turns read it,
the agent’s prompt substitutes it, and it is persisted with the call and merged
onto the contact record. Write there only what the conversation should still
know afterwards.
The default is tooldata. A booking reference the agent must be able to repeat
ten turns later belongs in userdata; the raw API envelope you unpacked to find
it does not.
Moving a value between operations
An operation’s result is not automatically visible to the next one.http,
code and frontend_rpc declare publish_fields, each entry
{path, key?, store}:
pathpicks a value out of the result by dotted path. A numeric segment indexes an array, soorder.items.0.nameis the first item’s name.keynames it. Left out, it is the last segment of the path —order.statuspublishes asstatus. Set it explicitly whenever the last segment is not the name you want to read back, and always when the path ends in an index.storeis required, and it is the difference between a value that dies with the tool and one the whole session carries.
set_variable writes one templated value directly, with the same required
store and no operation to produce it:
background_execution operation never waits for a result, so it cannot
publish. Setting both is a publish error.
What is an error, and what is a warning
Errors block publish; warnings do not. A key published anywhere earlier in the
tree counts as available, including inside an
if branch: keys published before
the branch are readable in both, and keys published inside a branch are readable
only later in that same branch.
One thing validation cannot catch: a secret that is deleted after the tool
was published. The next run fails at the start, before any operation, with
secret 'X' does not exist.
system_vars
Six keys, filled by the platform and writable by nothing.
So a tool can post the caller’s number to a CRM, stamp a record with
{{system_vars.now}}, or branch on the direction, without the agent having to
ask.
The three phone keys are empty on web calls, on text conversations and in a
dashboard test run. Never make one the only source of a fact the tool needs;
take it as an argument as well, or read it from userdata.
The clock keys read the moment the tool ran, not the moment the call
started — which is what makes {{system_vars.now}} right in a created_at you
send to an API forty minutes into a call. (In an agent’s prompt or greeting the
same tokens are frozen at the moment the agent started, because re-resolving
them every turn would throw away the model’s prompt cache.) They resolve
wherever the agent has a timezone set, on every channel.
vars
{{vars.name}} is the workspace’s own configuration for this session: the
agent’s declared defaults, with whatever the request that started the session
supplied merged over them. Read-only, and nothing inside the session can write
it. See variables for declaring them.
For a tool this is what removes the copy-per-customer problem:
{{vars.…}} names it reads are
checked against declarations only when an agent that attaches it is
published — and an undeclared name is a warning there, never an error.
Do not compare a clock string
{{system_vars.time}} is "7:26 PM" and {{system_vars.date}} is
"Wednesday, 19 August 2026". Neither is a number, and gt / lt need two
numbers — so an if comparing "7:26 PM" against "09:00" fails the
operation rather than quietly taking the else branch.
Business-hours logic belongs in a code operation over
new Date(input.system_vars.now). See
conditionals.
A worked example
Look up availability, keep three values with three different lifetimes, and read them back in a spoken line.requested_dateandheld_slot_idgo touserdata, so the next tool —book_appointment, called on a later turn — can read{{userdata.held_slot_id}}without asking the caller again, and the agent’s prompt can refer to the date.countandfirst_slotgo totooldata: they exist to build one sentence and have no business outliving it.- The header carries
{{system_vars.now}}— templating works in headers exactly as it does in the URL. - Because the only operation that could return a result is
silent, the tool is silent and the agent says thesayline and nothing else.
userdata, vars and a timezone alongside the arguments. See
testing and publishing.
Next
The HTTP operation
Every config field, auth, network rules and worked examples.
The code operation
The TypeScript sandbox,
input, and its real limits.Conditionals
Branching on a value an earlier operation published.
Secrets
Where
{{secrets.NAME}} comes from.