> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.ada.cx/docs/automation/playbooks/step-reference/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ada.cx/_mcp/server. # 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](/docs/automation/playbooks/configure#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](/docs/automation/playbooks/configure#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 type | Purpose | Modes | | :------------------- | :---------------------------------------------------------------------------------------- | :------------------------------------------ | | [`SEND`](#send) | Send a message to the end user | Fixed message, Contextual AI-generated | | [`SET`](#set) | Assign a variable value silently, without prompting the end user | Exact value, Use reasoning | | [`ASK`](#ask) | Ask the end user for a value | Capture exact response, Map using reasoning | | [`RUN`](#run) | Execute an API tool, Handoff, linked Playbook, Clear authentication, CSAT survey, or Exit | Deterministic only | | [`IF/ELSE`](#ifelse) | Branch the flow based on conditions | Deterministic only | | [`GO TO`](#go-to) | Jump to a specific step by ID | Deterministic only | > **Note** > > 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. > **Warning** > > 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](/docs/automation/playbooks/media) for supported channels and details. #### Search Knowledge in `SEND` steps A Contextual AI-generated `SEND` step can ground its reply in [Knowledge](/docs/knowledge). The step can search Knowledge when it runs, or reference specific articles. Both options appear under **Knowledge** in the `@` menu. * **Search Knowledge**: Use a search when the article that answers the end user depends on the conversation. * **Article reference**: Use an article reference when you know which article answers the end user at that point in the flow. > **Warning** > > Knowledge search and article references work only in Contextual AI-generated mode. In a Fixed message step, the **Search** pill and article references are removed from the message the end user receives, and no search runs. **Availability rules:** Both options follow availability rules. The search is the same Knowledge search the AI Agent uses elsewhere, and it does not return inactive articles. If a rule filters out a referenced article for a conversation, the Agent writes the reply without that article. **Conversations:** Step searches appear in the conversation's [reasoning log](/docs/optimization/conversations/response-training#reasoning-log) like other Knowledge searches, with the search term and the article snippets they retrieved. **To add a Knowledge search to a `SEND` step:** 1. In a Contextual AI-generated `SEND` step, type `@` to open the inline menu. 2. Under **Knowledge**, select **Search Knowledge**. A **Search** pill appears in the instruction. 3. Describe the topic of the search in the instruction. For example, "Use `@Search` to find the policy on delayed baggage claims, then explain how to file a claim." **How the search works:** When the step runs, the Agent writes a search query from the instruction and the recent conversation, then replies from the results. The query can use the value of any variable referenced in the instruction. If the Agent cannot write a query, it searches with the end user's latest message. **What the reply covers:** The Agent answers only the part of the end user's request that the instruction covers. If the search results do not contain what the instruction asks for, the Agent says that it does not have that information. **Search limits:** A step runs one search, even if its instruction contains more than one **Search** pill. Up to three steps can search Knowledge in one turn. After three, a step in the same turn does not run its search. **To reference an article in a `SEND` step:** 1. In a Contextual AI-generated `SEND` step, type `@` to open the inline menu. 2. Type part of the article title to filter the list. 3. Under **Knowledge**, select the article. > **Warning** > > A step can reference up to 5 articles, and can combine them with a search and variables. Each article row in the menu shows the article's locale. An article with [availability rules](/docs/knowledge/article-management#article-rules) also shows a people icon. Highlight the row to see the rule, for example "Available if plan is Enterprise". Inactive articles do not appear in the menu. **Inactive and deleted articles:** If a referenced article becomes inactive, its pill turns gray. If the article is deleted, the pill shows a short ID in place of the title. The Agent cannot use either article. Replace or remove the pill. ### SET Assigns one or more variable values without prompting the end user. `SET` operates in one of two modes: **Exact value** or **Use reasoning**. Neither mode asks the end user anything. > **Note** > > To ask the end user for input, use the [ASK](#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. This mode can resolve **several variables at once**, up to a maximum of 5. Each variable is configured as an **input** with its own accepted values and fallback value. The step keeps one instruction, which applies to every input. The Agent reads the transcript once and extracts every value in a single pass. The step stays silent, so the end user is never prompted. **Adding variables:** Type `@` at the start of the step, before the instruction text, then select a variable from the menu. Each variable you add appears as a pill and becomes an input. Repeat up to the maximum of 5. Delete a pill to remove that input. Typing `@` later in the instruction text has a different result. It inserts a reference to a variable's value. The Agent resolves the reference before it extracts. Use a reference when one variable's value needs to inform what the step extracts into another. A `SET` that resolves more than one variable always uses reasoning. Remove variables until one remains to switch the step back to **Exact value**. Each input is then resolved on its own. The Agent writes the value it extracts, as long as that value matches the input's accepted values. An input without a list of accepted values takes any extracted value. An input is unresolved when the Agent extracts no value, or extracts a value outside the accepted values. An unresolved input takes its fallback value. When an unresolved input has no fallback value, the Agent writes nothing. The variable keeps the value it already held. > **Note** > > Accepted values on a `SET` input are typed by hand. Building them from a data source is available on `ASK` steps only. See [Pull accepted values from a data source](#pull-accepted-values-from-a-data-source). > **Tip** > > 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:** | Field | Required | Description | | :-------------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Variable** | Yes | The target variable to write the captured value into. | | **Extraction instructions** | Yes | Instructions 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 mode** | Yes | How to capture the value — verbatim transcription or mapped using reasoning. | > **Warning** > > 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](#capture-exact-response) 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 3 times after the first question. After the last re-ask, 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 re-asks 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](#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](#quick-replies-for-accepted-values). * **Max re-ask attempts**: How many times the Agent re-asks the end user for a valid response after the first question before giving up. Accepts an integer from 0 to 20. A value of 0 asks the question once and never re-asks. When left empty, the system default of 3 re-asks 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. > **Note** > > 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). SMS capture is available only while [Agent SMS](/docs/channels/voice/voice-onboarding#control-whether-your-ai-agent-can-send-sms) is enabled. See [Voice call capture options](/docs/channels/voice/voice-configuration/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](#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](/docs/automation/variables/using-variables#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](#quick-replies-for-accepted-values). 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:** | Limit | Value | | :------------------------------------------ | :------------- | | Maximum length of a resolved value or label | 256 characters | | Maximum resolved values used for extraction | 100 | | Maximum quick replies shown to the end user | 10 | | Minimum values needed for quick replies | 2 | 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. > **Note** > > 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, CSAT survey, 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. * **CSAT survey**: Ask the end user to rate their experience. See [CSAT survey](#csat-survey). * **Exit**: Deterministically end the Playbook. #### Clear authentication [Playbooks](/docs/automation/playbooks) can request another Customer login after an end user selects the wrong account. > **Note** > > Clear authentication requires controlled access and supports structured v2 Playbooks in web chat. Select **Clear authentication** from **RUN** autocomplete. Choose the [Customer login provider](/docs/automation/tools/api-tools/token-configuration#customer-login-tokens). The built-in removes every credential that provider saved. This includes the access, refresh and identity credentials, and any extra field the provider returned. It preserves other providers' credentials and all business variables. It does not open login or run an API tool. **To add another login to a Playbook:** 1. Ask whether the end user wants to try another account. 2. Add a **Clear authentication** RUN step for the selected provider. 3. Use SET steps to clear saved account identifiers, lookup errors, eligibility decisions, and prior confirmations. 4. Add the existing account lookup as a separate RUN step. 5. Check the fresh lookup's success, error, and required account outputs before continuing. 6. Add explicit branches for unsuccessful lookup results, missing data, and the same account. Login cancellation and transport errors use the existing platform handling. If reset fails, execution pauses before the next step. When the lookup needs credentials, the existing authentication flow requests login and resumes that lookup afterward. Clear authentication does not erase earlier conversation messages or validate downstream API tool inputs. The author must ensure that account-dependent steps use the fresh lookup results. Reset does not end the provider's website session or revoke its Tokens. The next login can return the same account. Use the lookup result to identify the account that signed in. The built-in appears only in Playbook autocomplete, with no standalone **Tools** entry or Classic Playbook support. #### CSAT survey A [Playbook](/docs/automation/playbooks) can ask the end user to rate their experience at the point you choose. Turn on the **Enable AI Agent Survey** toggle in [CSAT survey configuration](/docs/optimization/performance/csat-survey/csat-survey-configuration) first. If the toggle is off, the AI Agent skips the step on every channel. Select **CSAT survey** from the **Tools** group in **RUN** autocomplete. How the survey reaches the end user depends on the channel: * **Web chat and messaging channels**: the AI Agent shows the survey card. * **Voice**: the AI Agent asks the caller for permission to send a text, then texts the survey link. If the caller declines, the AI Agent skips the survey. This requires [Agent SMS](/docs/channels/voice/voice-onboarding#control-whether-your-ai-agent-can-send-sms) and the caller's phone number. * **Email**: the AI Agent sends the survey link in its own email. The Playbook continues with the next step immediately. It does not wait for the rating. The AI Agent skips the survey when the end user already answered one in the conversation. When the survey ends the flow, place the step last or before an Exit. Responses appear in the [Satisfaction Survey Results](/docs/optimization/performance/reports/performance-reports#satisfaction-survey-results) report under the **CSAT block** survey type. Configure the survey style and questions in [CSAT survey configuration](/docs/optimization/performance/csat-survey/csat-survey-configuration). #### 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](/docs/automation/playbooks/best-practices#understand-when-set-is-needed-after-run). #### 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`. > **Warning** > > **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. #### Code tool error handling A Code tool fails when its code raises an error, exceeds a limit, or receives an input of the wrong type. You can build custom fallback behavior for any of these. For a Code tool's other outputs, you choose which part of the returned value to select. A failed run returns nothing, so those outputs are empty. The run status is the exception, so it is what you branch on. **To build a fallback path for a Code tool:** 1. In the Code tool's **Outputs** section, enable **Let playbooks branch when this tool fails**. Ada adds an output named `ada_run_status`. 2. Save that output to a variable. 3. `RUN` the Code tool. 4. `IF/ELSE` to check the variable. 5. In each branch, add recovery steps. For example, retry, send a message, or hand off. The status is `ok`, `timeout`, `error`, `invalid_input` or `disabled`. A `timeout` is the clearest case for a retry. See [Outputs](/docs/automation/tools/code-tools/inputs-outputs-and-environment#let-playbooks-branch-when-the-tool-fails) for what each value means. **Example:** 1. `RUN` `@verify_discount_code`. 2. `IF/ELSE`: if `@discount_run_status` is `ok`, `SEND` "Your discount has been applied." If it is `timeout`, `RUN` `@verify_discount_code` again. Otherwise, `SEND` "I could not check that code right now." Then `RUN` `@handoff_to_support`. > **Warning** > > The default and custom behavior match an API tool's. If no `IF/ELSE` condition references the run status variable, the Code tool exits the Playbook and hands off to a human agent. If a condition does reference it, the automatic handoff is disabled and you own the fallback path. > **Note** > > This behavior is rolling out. Until it reaches your AI Agent, the **Outputs** section does not show the setting, and a failed Code tool always hands off to a human agent. ### IF/ELSE Runs one of two step lists: the IF branch's steps when its conditions are true, otherwise the ELSE branch's steps, which may be empty. Add `ELSE IF` to test more conditions in order. #### Flat conditions The simplest form — a list of conditions evaluated together with a single logical operator. | Field | Required | Description | | :----------- | :------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `branches` | Yes | Exactly two branch objects. The first is the IF: its `conditions` (an array of condition objects) decide whether its `steps` run. The second is the ELSE: its `conditions` are empty, and its `steps` run otherwise. The ELSE is always required; with nothing to do, send `{"conditions": [], "steps": []}`, and the flow continues after the `IF/ELSE`. | | `conditions` | Yes (IF branch) | An array of condition objects. Each condition specifies a variable, an operator, and a value. | | `operator` | When the IF branch has more than one condition or group | The logical operator joining them: `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`. A chain at the top of a section can have one `IF` and up to nine `ELSE IF`s, then an `ELSE`. Each `ELSE IF` counts as one level of nesting, because it is stored as an `IF/ELSE` inside the previous `ELSE`. A Playbook allows 10 levels. More conditions in one `IF`, or separate `IF/ELSE` steps one after another, don't add levels. The editor also flags nesting deeper than 4 levels, counting the outermost `IF/ELSE` as level 1 and not counting `ELSE IF`. #### 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. | Field | Required | Description | | :------- | :------- | :-------------------------------------------------------------------------------------------------- | | `groups` | No | An array of Condition group objects. The branch's `operator` joins them with any flat `conditions`. | **Condition group fields:** | Field | Required | Description | | :----------- | :------- | :----------------------------------------------------------------------------------------- | | `operator` | Yes | `AND` or `OR` — the logical operator joining conditions within this group. | | `conditions` | Yes | An array of condition objects within this group. | | `groups` | No | Nested Condition group objects, up to 3 levels deep (the branch's own groups are level 1). | **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. | Field | Required | Description | | :--------------- | :------- | :----------------------------- | | `target_step_id` | Yes | The 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. > **Warning** > > 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. | Operator | Description | | :------------------- | :------------------------------------ | | **Is** | Exact match. | | **Is not** | Does not match. | | **Starts with** | Value begins with the specified text. | | **Ends with** | Value ends with the specified text. | | **Contains** | Value appears anywhere. | | **Does not contain** | Value does not appear. | | **Is set** | Variable has a value. | | **Is not set** | Variable has no value. | --- Have any questions? Contact your Ada team, or email us at [](mailto:help@ada.cx?subject=Help%20Docs%20inquiry).