Step reference

Overview

Playbooks use structured steps to guide AI Agents through multi-step workflows. Each step represents a discrete action the Agent performs during a conversation — sending a message, setting a variable, asking a question, running an action, branching on a condition, or jumping to another step.

Steps are organized into sections, which represent stages of the end user journey (for example, “Verify identity” or “Process refund”). Within each section, steps execute sequentially unless redirected by an IF/ELSE branch or a GO TO jump.

A Playbook also has General Guidelines that apply across all sections, providing the Agent with global context, tone guidance, and knowledge references.

Step types

The following step types are available when authoring Playbooks.

Step typePurposeModes
SENDSend a message to the end userFixed message, Contextual AI-generated
SETAssign a variable value silently, without prompting the end userExact value, Use reasoning
ASKAsk the end user for a valueCapture exact response, Map using reasoning
RUNExecute an API tool, Handoff, linked Playbook, or ExitDeterministic only
IF/ELSEBranch the flow based on conditionsDeterministic only
GO TOJump to a specific step by IDDeterministic only
For steps with multiple modes, click the step keyword to open the side pane, where you can switch between modes.

Step details

SEND

Sends a message to the end user. Use SEND steps to communicate information, provide instructions, confirm actions, or acknowledge end user input.

SEND has two modes:

Fixed message

Sends the exact message you author. The authored text is fixed — the Agent delivers your wording verbatim rather than generating new content. This is the key difference from Contextual AI-generated mode, where the Agent composes a new message from an instruction.

The message is processed by the LLM for delivery. In multilingual conversations, the LLM may translate the message into the end user’s language. The output stays as close to the original as possible, but exact wording is not guaranteed across languages.

Contextual AI-generated

The Agent generates a response based on the instruction you provide and the conversation context. Use this mode when the message should adapt to the situation rather than follow a fixed script.

Usage guidance:

  • Use SEND to provide context between backend operations (SET, RUN) so end users are not left waiting in silence.
  • Reference variables inline to personalize messages (for example, “Your order @order_id has been submitted.”).
  • Attach images inline using the @ menu. Images are delivered deterministically — the Agent sends the exact image you select at authoring time. Supports JPEG, PNG, and GIF. See Media for supported channels and details.

SET

Assigns a variable value without prompting the end user. SET operates in one of two modes: Exact value or Use reasoning. Neither mode asks the end user anything.

To ask the end user for input, use the ASK step instead.

Exact value

Assigns a literal value, a reference to another variable, or a math expression. Select the target variable, then provide the value.

  • The value is known at build time.
  • Setting one variable equal to another variable.
  • Computing a value with a math expression.
  • Use the value "NONE" to clear a variable (not an empty string).

Use reasoning

Silently extracts a value from the conversation using AI reasoning. The Agent reads the transcript and infers the value based on the instruction — it does not prompt the end user.

Select the target variable and provide an instruction describing what to extract. Optionally configure:

  • Accepted values: A list of allowed values. Constrains extraction to only these values. Pair with accepted values whenever the variable is used in a downstream IF/ELSE branch.
  • Fallback value: The value written when extraction fails or no accepted value matches. Set a fallback whenever the variable is used downstream.
You can add freeform context in the body of the step to provide additional extraction rules for the LLM. For example, if you need to explain complex extraction logic, write it directly in the step body alongside the instruction.

When to use reasoning mode:

  • Classifying or inferring a value from the conversation without prompting the end user.
  • Pair with accepted values whenever the result feeds into an IF/ELSE branch.
  • Set a fallback value at all times if the variable needs to exist downstream.
  • Start with normal reasoning effort; switch to high effort if adherence drops.

Example — extracting data from an API tool response:

  1. RUN @get_order_details to retrieve order information.
  2. SET (Use reasoning) @order_status with instruction: “Extract the order status from the action response” and accepted values: ["shipped", "processing", "canceled", "returned"], fallback: "unknown".
  3. IF/ELSE branch on @order_status.

ASK

Asks the end user for a value during the conversation. The Agent prompts the end user, extracts their response, and saves it to a variable. ASK has two modes:

Capture exact response

Captures direct input from the end user and saves it verbatim to one or more variables. Use this mode for straightforward inputs where you need the end user’s exact words — for example, first name, last name, email address, or order number.

This mode can set multiple variables at once from a single end user response, up to a maximum of 5. Each variable is configured as an input with its own extraction instructions and capture mode.

Input fields:

FieldRequiredDescription
VariableYesThe target variable to write the captured value into.
Extraction instructionsYesInstructions that tell the Agent how to extract this specific value from the end user’s response. For example, “Extract the 6-digit order number” or “Capture the email address”.
Capture modeYesHow to capture the value — verbatim transcription or mapped using reasoning.
Extraction instructions are required for each input. Leaving the field empty blocks saving and displays a validation error.

Map the answer using reasoning

Uses AI reasoning to interpret the end user’s response and map it to a value. Use this mode for inferred intents, preferences, or situations where the value is not a direct transcription — for example, mapping “I’d like a two-hour appointment” to a preference variable.

This mode can set one or more variables in one step, up to a maximum of 5. Each variable is configured as an input, the same way as in Capture exact response — see the Input fields table. When the step has more than one variable, the Agent asks for them together and extracts all of them from a single end user response. If the response provides only some of the values, the Agent saves those and re-asks for the ones still missing. The end user can correct any captured value before the step completes. Each variable has its own accepted values and fallback value.

Retry behavior: By default, the Agent re-asks up to 4 times. After the last attempt, the Agent keeps the values it already captured. Any variable still missing is set to its own fallback value if one is set, otherwise that variable is left untouched. You can change the number of attempts using the Max re-ask attempts field.

Configuration options:

  • When to ask: only_when_needed (default) — extract from the transcript first and ask only if the value is missing. always — skip extraction and always prompt the end user.
  • Question phrasing: contextual (default) — the Agent phrases the question naturally based on context. exact_words — the Agent uses the verbatim text you provide.
  • Accepted values: A list of allowed values. Restricts extraction to these values. The list can be typed by hand or built from an API tool’s output — see Pull accepted values from a data source. Accepted values can also be shown to the end user as tappable options — see Quick replies for accepted values.
  • Max re-ask attempts: The maximum number of times the Agent re-asks the end user for a valid response before giving up. Accepts an integer from 1 to 20. When left empty, the system default of 4 attempts is used.

When to use each mode:

  • Capture exact response: For simple, direct inputs where you don’t know the value in advance — first name, email, account number.
  • Map using reasoning: For complicated inferred intents or preferences, or when setting a variable to a known value based on interpretation (for example, mapping a preference to “two-hour appointment”).

Example — verifying end user identity:

  1. ASK (Capture exact response) @account_email — “Ask for the email address associated with their account.”
  2. RUN @verify_identity with @account_email as input.
  3. IF/ELSE branch on verification result.
On the Voice channel, each Ask-step variable also has Voice settings — a capture setting (how the caller provides the value: speech, keypad, or SMS) and a confirmation setting (whether and how the Agent reads the value back to confirm it). See Voice call capture options.

Quick replies for accepted values

An ASK step that uses Map the answer using reasoning can present its accepted values as tappable quick replies instead of requiring the end user to type an answer.

To turn this on, open the step’s Messaging channel settings and select Quick replies. The option is available when the step sets a single variable and has at least two accepted values.

Labels: Each accepted value can have a different display label, set in the accepted values list. The end user sees the label, and the Playbook receives the underlying value. When no label is set, the value itself is displayed.

Order: Quick replies follow the order of the accepted values list, so reordering that list reorders the options the end user sees.

Free text: The message box stays available while quick replies are shown. An end user can ignore the options and type an answer, which is extracted as usual.

Channel support: Quick replies are supported on the Web Chat widget only. All accepted values are shown as tappable options, in order. Values resolved from a data source are capped — see Pull accepted values from a data source.

Other channels are not supported yet. On those channels the Agent asks the question and the end user answers in the usual way — any options that appear there are not covered by this feature and their presentation may change.

Pull accepted values from a data source

Instead of typing a fixed list, an ASK step can build its accepted values from a variable holding a list — usually a variable an API tool saves its output to — so the options reflect the individual end user’s data. For example, an API tool that returns an end user’s open orders can produce one accepted value per order.

The list is resolved when the question is asked. Everything downstream — extraction, quick replies, branching — behaves exactly as it does with a hand-typed list.

To configure it:

  1. On the ASK step, select Add value for the variable — or Edit values if it already has accepted values.
  2. Select Pull from data source.
  3. Under Data source, select the variable that holds the list. Only Global Variables can be selected — not Sensitive Variables or Metavariables.
  4. In Define the value, write a template for the value the Playbook receives.
  5. Optionally, in Define the label, write a template for the text shown on the quick reply. Labels are only displayed when quick replies are on for the step; otherwise the value is used.

The step reads whatever the variable holds at runtime, so make sure a step earlier in the Playbook fills it — typically a RUN step whose API tool saves an output to that variable.

Preview the result: Select Show example, choose the API tool that fills the variable, then select Run API tool. The API tool runs with the test values saved in its own editor and the first row of its output is shown, along with the value and label the templates produce. Select a field name under the template to insert its placeholder. When no API tool saves an output to the selected variable, there is no example to show.

Templates: Use {{}} to reference a field from a row of the data — for example, {{order_id}} for the value and Order {{order_number}} for the label. Placeholders name fields of a single row and cannot use dot paths or reach nested objects. When the data is an array of plain strings, use {{item}} for the whole row. Define the value is required; when Define the label is empty, the value is displayed.

Data shape: The variable must hold an array of objects, or a JSON array stored in a text variable. An object containing exactly one array is unwrapped to that array.

Limits:

LimitValue
Maximum length of a resolved value or label256 characters
Maximum resolved values used for extraction100
Maximum quick replies shown to the end user10
Minimum values needed for quick replies2

Rows that produce a duplicate value, an empty placeholder, or an over-length value are skipped, as is a row whose label repeats an earlier row’s label — so keep the label template specific enough to stay unique. When more values resolve than the quick-reply limit, the extra values still count as valid answers even though they are not shown as options.

When the data source is empty, unreadable, or produces no usable rows, the step falls back to accepting free text: the Agent still asks the question and extracts the end user’s answer, with no accepted values applied. The Playbook does not error or stop.

The list is resolved again each time the step re-asks, so an API tool re-run mid-conversation is reflected in the options.

RUN

Executes an API tool, Handoff, linked Playbook, or Exit. RUN connects the Playbook to external systems and escalation paths. Each RUN step targets exactly one of:

  • API tool: Execute an API call or integration.
  • Handoff: Escalate the conversation to a human agent.
  • Linked Playbook: Call another Playbook. The parent pauses, the child runs to completion, then control returns.
  • Exit: Deterministically end the Playbook.

API tool output variables

When a RUN step executes an API tool, any outputs configured in the API tool’s output settings are automatically saved to their target variables. You do not need a SET step to capture these values — they are available for use in subsequent steps immediately after the RUN completes. You can branch on any auto-set output variable in a downstream IF/ELSE step — including the HTTP status code — without an intermediate SET.

Add a SET step after RUN only when you need to transform, rename, or derive a new value from the output. For guidance, see Best practices.

API tool error handling

When an API tool returns a 4xx or 5xx HTTP status code, you can build custom fallback behavior.

Pattern:

  1. RUN the API tool.
  2. SET (Exact value) a variable from the API tool response’s HTTP status code.
  3. IF/ELSE to check the status code.
  4. In the error branch, add recovery steps (retry, send a message, handoff).

Example:

  1. RUN @submit_refund.
  2. SET @refund_status_code = action response status.
  3. IF/ELSE: if @refund_status_code is 200, SEND “Your refund has been processed.” Otherwise, SEND “We’re having trouble processing your refund. Let me connect you with a specialist.” then RUN @handoff_to_support.

Default behavior (error code variable is NOT referenced in an IF/ELSE condition): the API tool exits the Playbook and hands off to a human agent automatically.

Custom behavior (error code variable IS referenced in an IF/ELSE condition): the automatic handoff is disabled — you must build the fallback path yourself.

IF/ELSE

Branches the flow based on conditions. Each branch contains its own sequence of steps that execute when the branch’s conditions evaluate to true. An optional default (else) branch handles cases where no conditions match.

Flat conditions

The simplest form — a list of conditions evaluated together with a single logical operator.

FieldRequiredDescription
branchesYesAn array of branch objects. Each branch contains conditions (an array of condition objects) and steps (the steps to execute if the branch matches).
conditionsYes (per branch)An array of condition objects. Each condition specifies a variable, an operator, and a value.
operatorYes (per branch)The logical operator joining conditions within the branch: AND or OR.

Example — branching on subscription status:

  • IF @subscription_status is active: SEND refund options.
  • ELSE IF @subscription_status is canceled: SEND reactivation instructions.
  • ELSE: RUN @handoff_to_support.

Multi-group conditions (nested AND/OR)

For complex logic that requires mixing AND and OR operators, branches support nested condition groups. Each group contains its own operator, conditions, and optionally nested sub-groups.

FieldRequiredDescription
groupsNoAn array of Condition group objects. When present, the flat conditions array is ignored.

Condition group fields:

FieldRequiredDescription
operatorYesAND or OR — the logical operator joining conditions within this group.
conditionsYesAn array of condition objects within this group.
groupsNoNested Condition group objects for further nesting (recursive).

Example — (A AND B) OR (C AND D):

groups: [
{ operator: "AND", conditions: [A, B] },
{ operator: "AND", conditions: [C, D] }
]
operator: "OR"

This evaluates to: (condition A AND condition B) OR (condition C AND condition D).

Example — VIP escalation with multiple criteria:

  • IF (@account_tier is vip AND @issue_severity is high) OR (@account_tier is enterprise): RUN @escalate_priority.
  • ELSE: continue standard flow.

GO TO

Jumps to a specific step by its ID, redirecting the flow within or across sections. Use GO TO to create loops, retry patterns, non-linear workflows, or to explicitly confirm which step comes next.

Without a GO TO, the Playbook automatically advances to the next step when the current one completes. Adding a GO TO that points to the next step is functionally equivalent but makes the intended flow explicit.

FieldRequiredDescription
target_step_idYesThe ID of the step to jump to.

When to use GO TO:

  • Confirming the next step at the end of an IF/ELSE branch for auditability.
  • Redirecting to a shared error-handling section.
  • Retrying a step after a failed validation.
  • Implementing loops (for example, re-asking after invalid input).
  • Skipping ahead when early conditions are met.
Backward GO TO steps (pointing to an earlier step) create loops. Always pair with an IF/ELSE condition that provides an exit path to avoid infinite loops.

Condition operators

The following operators are available in IF/ELSE conditions.

OperatorDescription
IsExact match.
Is notDoes not match.
Starts withValue begins with the specified text.
Ends withValue ends with the specified text.
ContainsValue appears anywhere.
Does not containValue does not appear.
Is setVariable has a value.
Is not setVariable has no value.