> For the complete documentation index, see [llms.txt](https://docs.graspil.com/en/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.graspil.com/en/app/automations.md).

# Automations

Automations are a visual builder that lets you set up your bot so it reacts to user actions on its own, without you doing anything manually: sending messages, passing data to other systems, changing user information, and more.

{% hint style="info" %}
You'll find this section in the dashboard at <https://app.graspil.com/workflows>
{% endhint %}

## Why you need this

Without automations, you'd have to send messages to every user by hand, or ask a developer to write custom code for every scenario. With automations, you set up a scenario once using a visual, drag-and-drop builder (no code required) — and from then on, the bot keeps running it by itself, continuously, for every user it applies to.

Examples of what you can build:

* A user pays for an order → 5 minutes later, send them a thank-you message with a link to support chat.
* A user signs up but doesn't take any action for 3 days → send them a reminder about the bot.
* Every Monday at 10:00 → send a stats report to your Telegram channel via webhook.
* A user submits a request → automatically create a deal in your CRM.
* A user reaches a certain activity level → set a custom field "VIP" on them, so you can use it later in broadcasts and reports.
* The bot sends a message with buttons — for example, a survey "Did you like the service?" with "Yes" and "No" buttons → depending on which button the user taps, instantly continue with its own branch of the scenario — this is how you can build simple polls, quizzes, and multiple-choice menus (see the buttons section below for details).

## What an automation is made of

Every automation is built from blocks that you connect with arrows on a canvas — much like a flowchart. There are four types of blocks:

| Block         | What it does                                                                              |
| ------------- | ----------------------------------------------------------------------------------------- |
| **Trigger**   | What starts everything. Every automation has exactly one                                  |
| **Action**    | What to actually do (send a message, call a webhook, etc.)                                |
| **Condition** | A fork: if the condition is true, follow one branch; if not, follow another               |
| **Wait**      | A pause before the next step — either for a set amount of time, or until an event happens |

In plain terms: the trigger answers "when should this run?", actions answer "what should happen?", conditions answer "what if I need different behavior for different users?", and wait blocks answer "what if I need to do something not right away, but after some time?".

## How to create an automation

1. Open the **"Automations"** section in the dashboard and click **"Create automation"**.
2. Give it a name (only visible to you — just to tell automations apart) and select the bot it's for.
3. After creating it, you land on the automation's page, where you can see its status, run statistics, and version history.
4. Click the pencil icon — **"Edit in builder"** — to open the visual canvas and build the diagram.

### Building the diagram on the canvas

On the right side of the canvas there's an **"Add block"** panel with three groups: **Triggers**, **Logic**, **Actions**.

1. Start by adding a trigger — it will appear as the first block on the canvas. You can only add one trigger — once it exists, the trigger section in the panel disappears.
2. Add one or more action, logic, or wait blocks, depending on your scenario.
3. Connect the blocks with arrows: grab the output "handle" of one block and drag it to the next one. Each output can only have one outgoing arrow — dragging a new connection replaces the old one.
4. To remove a connection between blocks, click the arrow — a "Delete" button will appear.
5. To configure a block itself, click on it — a settings panel will open (what's in it depends on the block type, see the sections below).

{% hint style="warning" %}
If the diagram has no trigger, no actions, or some blocks aren't connected to each other, you won't be able to publish the automation. The system will show you exactly what needs to be fixed.
{% endhint %}

## Trigger — what starts the automation

When setting up the trigger, choose the **"Launch type"**:

* **"By event"** — the automation runs whenever a user completes one of the selected events (e.g. "payment", "sign-up"). You can pick several events at once — any of them will trigger it. This is the same event list used in reports — see [Event reference](/en/app/reports/events.md) for details.
* **"On a schedule"** — the automation runs on a timer: you specify the **frequency** (every day / once a week / once a month / once a year) and the **launch time**.
* **"Manual launch"** — the automation doesn't run by itself; you trigger it yourself (e.g. for testing).

For "By event" and "On a schedule" triggers, you can also click **"Configure filters"** to narrow down exactly which users the automation applies to — for example, only users on a certain plan or with a certain interface language. This filter works the same way as the broadcast audience filter.

## Actions — what the bot should do

Available actions:

| Action                         | What it does                                                                                                                                                                                                                                                                                        |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Send message**               | Sends the user a Telegram message — text, photo, video, document, etc., optionally with buttons. The text can be personalized by inserting the user's name and other data                                                                                                                           |
| **Webhook**                    | Sends a request to your server or an external service — handy for passing user data into your own system                                                                                                                                                                                            |
| **Create event**               | Records a new event in analytics — useful if you want to build a report on how the automation performed                                                                                                                                                                                             |
| **Change custom field**        | Changes the value of a user's [custom field](/en/app/custom-fields.md) — set a value, or increase/decrease a number                                                                                                                                                                                 |
| **AI agent**                   | Hands the situation to a language model with a fixed menu of outcomes to choose from — the model decides what to do next on every run. See "AI agent" below for details                                                                                                                             |
| **Referral program**           | Runs referral-program operations right from the scenario: register a referrer, get their code/link, check their balance, request a payout. See [Referral system](/en/app/referral-system.md) for details                                                                                            |
| **Channel subscription check** | Checks whether the user is subscribed to a chosen Telegram channel — gives you separate "subscribed" / "not subscribed" branches right away                                                                                                                                                         |
| **Join request**               | Approves or declines a user's request to join a private channel or group                                                                                                                                                                                                                            |
| **Delete message**             | Deletes a previously sent or received message in the chat with the user — for example, to remove a user's reply once it's been used further in the scenario                                                                                                                                         |
| **Integrations**               | Send data to an external service, e.g. create a deal in a CRM (amoCRM, Bitrix24), send an offline conversion to Yandex.Metrika, a conversion postback to the Keitaro tracker, or accept a payment in the bot via YooKassa — see [Case: accepting payments via YooKassa](/en/cases/case-yookassa.md) |

{% hint style="info" %}
For integration actions you need to set up the integration itself in the dashboard beforehand — the action won't work without it. The list of available integrations keeps growing. If you don't see the integration you need, message us — we'll add it within a few days.
{% endhint %}

Text fields inside actions (like the message text) support variables — they're automatically replaced with real user or event data at the moment of sending. For example, if you insert the user's name, every recipient sees their own name. See the "Variables" section below for the full list of where variables come from, including ones you can define yourself.

You can add buttons (an inline keyboard) to a message — for example, for a survey or a menu of choices. When adding a button, pick the **"Continue scenario"** type for it — the button then becomes its own separate output from the "Send message" block: you can drag an arrow from it further down the diagram, just like from a regular block. One tap, one output — a message can have as many "Continue scenario" buttons as you like, each with its own branch. See "Buttons that continue the scenario" below for details.

Buttons of other types (a plain `url` link, or a button carrying custom data for an external integration) aren't involved in automation branching.

### Sending the message in the recipient's language

If your bot has a multilingual audience, you don't need a separate "Condition" branch per language. The "Send message" block has a language switcher above the text field:

1. Click "+" next to the **"Default"** tab and pick a language from the list — it's built automatically from the languages your bot's users actually have.
2. On the new tab, write the text for that language — it's a separate variant, not a copy of the default text.
3. You can add as many languages as you like. The rest of the block's settings (buttons, media, file) stay shared across all languages — only the text/caption switches.

When the automation reaches this block, the bot checks the recipient's Telegram interface language and sends whichever text variant you've set up for it. If there's no variant for that recipient's language, the "Default" text is sent instead. If you never touch the language switcher, nothing changes — everyone gets the same text, exactly as before.

## AI agent — let a language model decide

The "AI agent" block is a special kind of action: instead of hand-coding "if — then" logic, you describe the situation in a prompt and give the model a menu of things it's allowed to do — and it's the model that decides what to pick, on every run.

What you configure in the block:

* **Prompt** — the context and the rule the model should use to decide. You can insert variables into the prompt: user and event data, custom fields, and results from earlier nodes in the diagram.
* **Outcomes** — a fixed menu of what the model is allowed to do:

  * **Send message** — the model writes the text itself and sends it to the user (the current user by default, or a fixed `user_id` if you set one).
  * **Change custom field**.
  * **Continue with no action**.
  * **Decision branch** — an outcome with no side effect, just a path choice: you describe when this branch applies (e.g. "the user's message is the correct answer to the question"), and the model picks whichever branch fits its own description. You can add as many decision branches as you like — each gets its own separate output on the canvas, just like a regular condition.

  Only one outcome with a side effect (i.e. not a branch) can fire per run — the model picks a single matching outcome.
* **Access to the user's messages** (optional) — you can let the model see recent conversation history with the user: the last N messages, or messages from the last N minutes, incoming/outgoing or both. This adds context for the model but isn't required.
* **Indicator while generating** — what the user sees while the model is composing its response: nothing, a "typing…" status, or a live draft that updates as the response is generated. Plain sending (no indicator) is the most predictable option; Telegram may not have time to show the indicator if generation is fast.

{% hint style="info" %}
**Billing:** every run of the AI node is billed separately, based on the token count of the chosen model (input and output, price already includes the platform markup) — the spend shows up in the resource's billing.
{% endhint %}

**Example use case:** a bot runs a quiz. The prompt tells the model to check whether the user's message is the correct answer to the question that was asked. Two decision branches are set up — "Correct answer" and "Wrong answer" — each with a description of when it applies. The model reads the user's latest message (via access to the conversation) and picks which branch to follow — from each branch you can build your own chain of "Send message", "Condition", and so on.

## Condition — different logic for different users

A "Condition" block creates a fork in the diagram: if the condition is true, execution follows one arrow from the block; if it's false, it follows the other arrow (if you've drawn one) — or simply stops.

To configure a condition, click the block and select **"Configure condition"** — this opens the same condition builder used for broadcast audiences: you can check user fields (language, sign-up date, custom fields, etc.), compare them, and combine several conditions with "AND"/"OR".

**Example:** "If the user's custom field 'Plan' is set to 'Premium' → send one message, otherwise → send a different one."

## Switch — several branches off a single value

A "Condition" block is a fork with two outcomes (yes/no). "Switch" lets you split the scenario into several branches at once, based on the value of a single field — instead of chaining several conditions in a row.

To configure it, click the block and select **"Configure cases"**. Each case is its own condition (configured the same way as in a "Condition" block) with its own separate output on the canvas. Cases are checked top to bottom, and the first one that matches wins. Besides the cases, the block always has a separate **"Other"** output — the scenario follows it whenever no case matched; there's nothing to configure for it, it's always there.

**Example:** a user has a custom field "Plan" — case "Free" → an upgrade offer message, case "Standard" → a message about available add-ons, case "Premium" → send nothing; the "Other" output covers users where the field isn't set at all.

## Wait — a pause before the next step

There are two kinds of wait blocks:

* **Wait for time** — simply pauses for a set amount of time (e.g. wait 1 hour) before moving on to the next block.
* **Wait for event** — pauses until the user completes a chosen event, but no longer than a specified timeout. If the event never happens, execution continues along the timeout path.

**Example use case:** "User places an order → wait for the 'payment' event for up to 30 minutes → if payment happened, send a thank-you; if not, send a reminder about the unfinished order."

## Variables

Text fields inside actions (message text, a webhook URL, a custom field's value, and so on) support variables — they're replaced with real data when the automation runs. There are several sources of variables:

* **User and event data** — for example, the user's name, or the value of the event that triggered the automation.
* **Data written by earlier nodes in the diagram** — for example, a webhook's response (if its settings say which response field to save into which variable), or whatever the user typed while the diagram was paused on "Wait for event".
* **Init variables** — set once, when the automation starts, on the **"Variables"** tab in the builder's side panel (the "Blocks" / "Variables" switch at the top of the panel). Give it a name and a value (you can insert a variable or a JSON array) — this variable is then available in every node in the diagram right from the start, before the first action even runs.
* **The "Set variable" block** — a separate node in the "Logic" group: it computes a value (which can itself reference variables) and stores it under a name you give it, right at that point in execution — from this node onward, the variable is available everywhere further down the graph. Handy when you need to compute or copy a value once and reuse it in several later nodes.

All variables are substituted into templates the same way, regardless of where they come from. Text fields in the builder have an "insert variable" button that shows both the init variables and every variable written by a node in the diagram, labeled with which node wrote it.

## Buttons that continue the scenario

The simplest way to build a poll, quiz, or choice menu is buttons of the **"Continue scenario"** type on a "Send message" block (see Actions above).

1. In a "Send message" block, add a button and pick the **"Continue scenario"** type for it.
2. The block gains a separate output for that button on the canvas — drag an arrow from it to the next block, same as usual.
3. With several such buttons, each has its own output and its own branch: the user sees one message with several buttons, and the scenario continues along whichever branch matches the button they tapped.

{% hint style="info" %}
This kind of button isn't one-shot — it keeps working after the first tap, and the scenario fires again if the user taps it (or another button on the same message) again. This is handy for a persistent menu that can be tapped any number of times.
{% endhint %}

**Example use case:** "The bot sends 'Did you like the service?' with 'Yes' and 'No' buttons → the 'Yes' branch sends a thank-you, the 'No' branch asks for details about the problem."

{% hint style="warning" %}
This is different from a regular "Wait for event" block: there you manually pick a single event and configure a timeout with its own branch, while a "Continue scenario" button creates the branching automatically, without a separate wait block on the canvas.
{% endhint %}

## Dynamic buttons — one button per list item

If the set of buttons isn't known in advance and depends on data — for example, a list of available appointment slots returned by a webhook — you don't need to add buttons one by one by hand. There's a dedicated button type for this: **"Dynamic list"**.

1. In a "Send message" block, add a button and pick the **"Dynamic list"** type for it.
2. Point it at the variable that holds the array (for example, a variable that a webhook or a "Set variable" block saved the list of slots into).
3. Set the button text template — it's applied to each array item individually, generating one button per item with that item's data.
4. All the resulting buttons lead to one shared output — wherever the user taps, the scenario continues along the same branch. To find out which item the user actually picked, turn on **"Save to variables on click"** and specify which fields of the item go into which variables — from there on, you can use those variables normally, further down the graph.

**Example use case:** the bot shows available appointment slots fetched by a webhook — the user taps the date they want, and it's saved into a variable that's then used both in the confirmation message and in the booking webhook.

{% hint style="info" %}
Up to 20 buttons per message (Telegram's limit for inline keyboards). If the array has more items than that, the extra ones aren't shown.
{% endhint %}

## Saving, testing, and publishing

* Changes to the diagram are saved as a **draft** — you can edit it as many times as you like, nothing breaks until you actually publish.
* The **"Run test"** button (play icon) lets you check how the diagram behaves with test data, without sending anything to real users — useful to make sure everything's configured correctly before turning the automation on for everyone.
* Once everything's ready, click **"Publish"**. From that moment, the automation starts running on its own: it watches for its trigger and runs its actions for every matching user, without any further action from you.
* If there are errors in the diagram (for example, no event selected for the trigger, or an action isn't filled in), the system will show a list of what needs fixing and won't let you publish until they're resolved.

{% hint style="info" %}
A published diagram doesn't change on the fly. If you want to tweak a running automation, your changes are saved as a new draft version — the old version keeps running exactly as before until you publish the new one.
{% endhint %}

## Automation statuses

| Status       | What it means                                                               |
| ------------ | --------------------------------------------------------------------------- |
| **Draft**    | The diagram hasn't been published yet, the automation isn't running         |
| **Active**   | The automation is published and running                                     |
| **Stopped**  | The automation was stopped manually — temporarily inactive, but not deleted |
| **Archived** | The automation has been archived                                            |
| **Error**    | Something went wrong during a run — worth checking your action settings     |

To temporarily turn off a running automation, open it and click **"Stop"**. To turn it back on, publish the version you want active again.

## Configuring concurrent runs

If the same user can trigger the automation again before a previous run for them has finished (for example, with an event-based trigger and frequent events), you can control this behavior via the gear/sliders icon on the canvas:

| Option                 | What happens                                                                                   |
| ---------------------- | ---------------------------------------------------------------------------------------------- |
| **Parallel (default)** | Every run executes independently, even if a previous one for the same user hasn't finished yet |
| **Cancel previous**    | A new run cancels the still-running previous one and starts fresh                              |
| **Ignore new**         | While one run is in progress for a user, new trigger events for them are ignored               |

## Version history and statistics

On the automation's main page (not the builder, but the overview page with its settings), you'll find:

* **Version history** — every saved draft and published version; any of them can be opened in the builder for editing, or published again.
* **Statistics** — how many times the automation has run, how many runs failed, how many unique users it ran for, shown as a chart over a chosen period.
* **Runs (executions)** — a list of recent runs with the user, status, and time; failed runs have a retry button, plus an error log showing exactly which block in the diagram something went wrong on.

## Running an automation for a chosen audience (like a broadcast)

Besides triggering automatically, a published automation can also be run manually for an entire audience of users at once — the same way you'd launch a regular broadcast.

1. Go to the **"Broadcasts"** section → **"Create campaign"**.
2. On the campaign-type step, select the **"Run automation"** card.
3. Build the audience using the same builder as for a regular broadcast (all users, by conditions, by list, etc.).
4. Pick the automation you want from the **"Select a workflow to run"** list — only already-published automations are available here.
5. Launch the campaign — the automation will run for every user in the chosen audience, exactly as if its trigger had fired for them.

This is handy when you want to run an existing scenario (say, a multi-step message chain with conditions and waits) once against a specific list of users, instead of setting up a separate trigger for it.

## Deleting

You can delete an automation from the list ("Automations" → trash icon on the row) or from the automation's own page. Deletion is permanent — it removes the automation along with all its versions and run history.

{% hint style="info" %}
Want to manage automations programmatically from your own system instead of through the dashboard? See the [Automations API documentation](/en/api/automations.md).
{% endhint %}
