For the complete documentation index, see llms.txt. Any page on this site can be fetched as Markdown by appending .md to its URL.

System Variables

Every $(sys.*) value a workflow can reference — execution context, caller data, and date/time — with its type and when it's available.

Alongside the variables your flow sets, every run carries a set of system variables the platform fills in for you: which workflow is running, who called, what the current time is. Reference them exactly like your own variables — $(sys.ctx.conversation_id) — anywhere a field accepts $( ).

System variables are read-only from a Set Variable node — it cannot create or overwrite anything under sys., the write is rejected.

Two ways to write a reference

$(sys.date.now) and {{sys.date.now}} are equivalent — same grammar, same result. Use whichever you prefer; the editor's suggestion menu completes whichever one you start typing. To write a literal delimiter instead of a reference, escape it with a backslash: \$( or \{{.

Show references as

Every reference below follows your choice.

Two clocks: sys.date and sys.utc

Date and time come in two namespaces with identical fields. $(sys.date.*) is the workflow's own timezone, set in workflow settings; $(sys.utc.*) is UTC. A workflow with no timezone configured falls back to America/New_York.

Within a single node, every date reference is evaluated once, so $(sys.date.minute) and $(sys.date.second) in the same field can't straddle a tick.

When a variable isn't there

Anything marked Optional depends on how the conversation started — telephony fields need a phone call, SMS fields need an inbound message, and a carrier may not supply a caller name at all. An optional value that wasn't supplied resolves to an empty string when you interpolate it into text, so a message body of $(sys.telephony.ani) renders as nothing at all on a conversation that didn't start with a phone call. To branch on whether a value was supplied, use a Condition node's Exists or Does Not Exist operator rather than relying on the rendered text.

Reference

Show references as

Execution Context

Identifiers and metadata about the running workflow and conversation.

Always available.

ReferenceTypeDescription
$(sys.ctx.workflow_id)stringCurrent workflow ID
$(sys.ctx.workflow_instance_id)stringCurrent workflow instance ID
$(sys.ctx.conversation_id)stringCurrent conversation ID
$(sys.ctx.organization_id)stringCurrent organization ID
$(sys.ctx.conversation_type)stringChannel/type of the current conversation
$(sys.ctx.workflow_name)stringName of the current workflow
$(sys.ctx.version)stringVersion of the current workflow
$(sys.ctx.timezone)stringTimezone of the current workflow

Telephony

Optional

Caller and dialed-number data supplied by the originating call.

Only when a phone call starts the workflow, and only for the fields the carrier supplies.

ReferenceTypeDescription
$(sys.telephony.ani)stringCaller number
$(sys.telephony.dnis)stringDialed number
$(sys.telephony.cnam)stringCaller name
$(sys.telephony.callTag)stringSharpen call identifier, when the call arrived from Sharpen

Inbound SMS

Optional

The message that started the workflow.

Only when an inbound SMS starts the workflow.

ReferenceTypeDescription
$(sys.sms.body)stringInbound message text that started the workflow
$(sys.sms.from)stringSender's phone number
$(sys.sms.to)stringBandwidth number that received the message

Web Chat

Optional

The website visitor and the message that started the workflow.

Only when a chat widget starts the workflow.

ReferenceTypeDescription
$(sys.chat.message)stringThe visitor's first message, which started the workflow
$(sys.chat.visitorId)stringOpaque id for the visitor's browser, stable across their visits
$(sys.chat.widgetId)stringId of the chat widget the visitor opened

Caught Error

Optional

What failed inside a Try / Catch group.

Only in a Try / Catch group's catch branch. Elsewhere they hold the last catch's values, or nothing at all if no catch has run in this conversation, so an empty sys.error.node does not mean nothing failed. A later catch overwrites them; if that write fails, the earlier catch's values stay in place.

ReferenceTypeDescription
$(sys.error.node)stringName of the node inside the group whose outcome was caught
$(sys.error.exit)stringThe exit that node took, e.g. fallback or invalidInput; exits like timeout appear only with "Catch every unhandled exit" turned on
$(sys.error.message)stringThe failure text the node reported

Scheduled Run

Optional

Facts about a run that a Schedule Workflow node or agent started.

Only on a run a schedule started.

ReferenceTypeDescription
$(sys.schedule.depth)numberHow many scheduled runs led to this one; absent means 0

Date & Time

The current date and time. Every field below is available twice: in the workflow's timezone as $(sys.date.*), and in UTC as $(sys.utc.*).

Always available.

ReferenceTypeDescription
$(sys.date.now), $(sys.utc.now)stringISO date-time
$(sys.date.day), $(sys.utc.day)numberDay of month
$(sys.date.weekday_num), $(sys.utc.weekday_num)numberWeekday number (1=Mon)
$(sys.date.weekday_long), $(sys.utc.weekday_long)stringFull weekday name
$(sys.date.weekday_short), $(sys.utc.weekday_short)stringShort weekday name
$(sys.date.month), $(sys.utc.month)numberMonth (1-12)
$(sys.date.month_long), $(sys.utc.month_long)stringFull month name
$(sys.date.month_short), $(sys.utc.month_short)stringShort month name
$(sys.date.year), $(sys.utc.year)numberFour-digit year
$(sys.date.hour_24), $(sys.utc.hour_24)numberHour (0-23)
$(sys.date.hour), $(sys.utc.hour)stringHour (1-12)
$(sys.date.minute), $(sys.utc.minute)numberMinute (0-59)
$(sys.date.second), $(sys.utc.second)numberSecond (0-59)
$(sys.date.timezone), $(sys.utc.timezone)stringTimezone name
$(sys.date.offset), $(sys.utc.offset)numberUTC offset in hours
$(sys.date.time_24), $(sys.utc.time_24)string24h time
$(sys.date.time), $(sys.utc.time)string12h time
$(sys.date.time_long), $(sys.utc.time_long)stringLong time
$(sys.date.time_long_12), $(sys.utc.time_long_12)stringLong 12h time
$(sys.date.date_short), $(sys.utc.date_short)stringShort date
$(sys.date.date_med), $(sys.utc.date_med)stringMedium date
$(sys.date.date_long), $(sys.utc.date_long)stringLong date
$(sys.date.date_huge), $(sys.utc.date_huge)stringFull date
$(sys.date.date_time_short), $(sys.utc.date_time_short)stringShort date-time
$(sys.date.date_time_med), $(sys.utc.date_time_med)stringMedium date-time
$(sys.date.date_time_long), $(sys.utc.date_time_long)stringLong date-time
$(sys.date.date_time_huge), $(sys.utc.date_time_huge)stringFull date-time

The other namespaces

sys. is one of five namespaces a reference can name. The other four hold values you set yourself, and they are read in different places: a workflow node reads its own variables and $(sys.*), while a voice agent's configuration reads three more.

NamespaceWhat it holdsWhere it's setWhere it resolves
sys.Call and workflow context the platform fills in for youThe platformWorkflow nodes; in agent configuration, only the subset below
org.<name>Organization-wide values shared by every agentAdmin → Secrets & VariablesVoice agent configuration
secrets.<name>Organization-wide credentials. Write-only — no API returns a valueAdmin → Secrets & VariablesOnly in an integration tool's constant parameters and request path, as the request is sent
agent.<name>One agent's own valuesThe agent's Variables sectionThat agent's configuration
vars.<name>Per-call values a workflow hands to an agentThe AI Voice Agent node's Pass to agent listThat agent's configuration, for the call it was passed on

A workflow node resolves sys. and your own flow variables — and nothing else. org., secrets., agent., and vars. all render as an empty string there, with no error. They are for voice agent configuration.

Full details, and how to create the values, are on Secrets & Variables.

An organization-wide value

Create a variable named brand with the value Northwind Traders, then write an agent's system prompt against it:

You are the virtual receptionist for {{org.brand}}.

Change the variable once and every agent that references it picks up the new value. Nothing needs to be re-saved. Allow up to five minutes for the change to reach every call; When a change takes effect explains why.

A value for one agent

Add a variable named queue with the value Billing in that agent's Variables section, then reference it in the same agent's prompt:

Transfer to the {{agent.queue}} team when the caller asks about an invoice.

An agent. name is visible only to the agent that declares it. Two agents can each have a queue with different values.

A secret resolves in one place only

A secret is deliberately harder to use than a variable. {{secrets.stripe_key}} is resolved in one place only — the outbound HTTP request an integration tool makes — so it may appear only in that tool's constant parameters and its request path. Anywhere else (a prompt, a greeting, a disposition, an agent variable) is rejected when you save.

That is the point of the design: if a prompt leaks, it leaks the text {{secrets.stripe_key}} rather than the key.

Only the {{ }} spelling works for a secret. Everywhere else on the platform the two spellings are interchangeable. A secret is matched as the request leaves, against the exact form {{secrets.name}}, so a $(secrets.name) is refused rather than resolved. Saving an agent that references a secret also requires the organization administrator role.

A value for one call

A workflow can hand an agent values that change call to call — a customer id, an account tier, the result of a lookup it already did — through the AI Voice Agent node's Pass to agent list. The agent reads them as {{vars.<name>}} in its prompt, greeting, thinking cue, disposition descriptions, and an integration tool's constant parameters.

Greet the caller by name. Their account tier is {{vars.tier}}.

They travel one way. A name the workflow didn't pass reads as empty rather than failing the call, and the values are fixed at the moment of the handover. See Secrets & Variables for the limits.

Functions don't work in agent configuration

{{UPPER(org.brand)}} is valid in a workflow node. In agent configuration, and in an org variable's value, a function call is rejected — use a plain reference instead.

In a voice agent, only part of sys. resolves

An agent session has no workflow behind it, so the tokens that describe one have nothing to read. These are the sys. tokens an agent's configuration accepts:

  • Context: $(sys.ctx.conversation_id), $(sys.ctx.organization_id), and $(sys.ctx.agent_id) — the last exists only for agents, which is why it isn't in the reference table above.
  • Telephony: $(sys.telephony.ani), the other party's number. On an inbound call that's the caller's number. On an outbound call placed by a Convert to Voice node, it's the number that was dialed, not your caller ID. It is the only telephony field an agent session receives.
  • Date and time: every $(sys.utc.*) field.

Everything else is refused when you save the agent, with is not available to a voice agent. That covers $(sys.ctx.workflow_id), $(sys.ctx.workflow_instance_id), $(sys.ctx.workflow_name), $(sys.ctx.version), $(sys.ctx.conversation_type), $(sys.ctx.timezone), all three $(sys.sms.*) fields, $(sys.telephony.dnis), $(sys.telephony.cnam), and every $(sys.date.*) field.

Use $(sys.utc.*) for the time in an agent, not $(sys.date.*). A workflow reads $(sys.date.*) in the timezone set in its settings, and an agent has no workflow behind it to supply one, so rather than answer in a zone you did not choose, an agent refuses the token at save time. UTC is correct without configuration, which is why it is the one that resolves.

Next steps

On this page