Variables and extraction
Variables carry data through a conversation. They arrive in two ways: you pass them in, or the agent captures them from what the caller says.
Passing variables in
Variables are seeded when a session starts - a customer's name, an account tier, an order reference - and are available immediately, so the agent can open with them. They can come from:
- The sessions API -
variableswhen you open a session withPOST /workflows/{uuid}/sessions. - The calls API -
variableson atextcall. Aphonecall placed through the calls API does not carry them. - A campaign - every column of a contact's row other than the phone number becomes a variable for that contact's call. See Campaigns.
- Your server - set
dynamic_config_urlon the agent and Glytos POSTs{"workflow_uuid": ..., "mode": ...}to it as every session starts, on any channel. Avariablesobject in the JSON reply is merged in; variables passed explicitly win over it. If the request fails or times out (10 seconds) the session starts without them. - The Playground, for testing.
The public browser chat and a browser web call have no way to pass variables
directly; use dynamic_config_url for those.
Use them in any prompt or message with {{name}}. Nested values are reached with a
dot, as in {{customer.tier}}:
Greet {{customer_name}} by name and confirm you are calling about order {{order_id}}.A variable that is not set renders as nothing, not as the placeholder.
Hello {{customer_name}}. becomes Hello . when no name was passed, so write
prompts that still read correctly when a variable is missing.
In a workflow, variables can also be used in edge conditions, so the conversation can branch on data you already had before the caller said a word.
Capturing what the caller says
Extraction pulls structured values out of the conversation. It is configured per
conversation node (on a prompt agent, on the agent) under extract. Each field has a
name and a hint telling the model what to look for:
| Field | Hint |
|---|---|
full_name | The caller's full name |
callback_number | A phone number to call back on |
preferred_day | The day they want the appointment |
Extraction runs on each caller turn at that step, over the conversation so far.
Captured values become variables, so a later step can use {{full_name}}.
Extraction captures what was said - it does not make the agent ask. The prompt has to actually ask for each field. This is the most common reason a field comes back empty.
Required fields and retries
required is a list of field names inside extract:
{
"fields": [
{ "name": "full_name", "hint": "The caller's full name" },
{ "name": "callback_number", "hint": "A phone number to call back on" }
],
"required": ["full_name", "callback_number"],
"retry_message": "Sorry, could you give me your name and a number to call back on?",
"max_retries": 2
}After each caller turn, if a required field is still empty, the agent replies with
retry_message instead of moving on or answering from the model. It does this up to
max_retries times at that step (default 2); after that the conversation continues
normally rather than trapping the caller in a loop. Without a retry_message a short
generic line is used.
Where captured values end up
Variables are stored on the session, visible in the dashboard, included in the
end-of-call report, and delivered on the session.completed
webhook - which is how they reach your CRM.
A chat session completes, and session.completed fires, only when the conversation
reaches an end - an end step, a matched end phrase, or the max_turns limit. A chat
that is simply abandoned stays open and sends no session.completed.