Automations
Automations lets you wire up multi-step workflows — think Zapier or n8n, but built for your contacts and conversations.
Automations is available on every account — it’s already in your sidebar, and there’s nothing to enable or request.
An Automation is a workflow: one trigger that starts it, followed by any number of steps that run in order (or branch, based on a condition). It’s the tool for anything more involved than “send this opener, hand replies to an Agent” — multi-step sequences, data lookups, connecting to outside tools, and logic that branches depending on what a contact does.
Where to find it: In the sidebar, under the AI Studio group, click Automations.

The Automations page before you've built anything.
Creating an Automation
Click Create your first automation (or New automation once you have others). You land on an empty canvas with two ways to build:
-
Describe it in plain English. Type what you want in the prompt box (for example “Send a follow-up if there’s no reply in 1 hour”, “Tag contacts who ask about pricing”, or “Give my AI agent a way to look up an order status”) and it builds the trigger and steps for you (including AI Agent Function tools your agent can call). You can keep chatting to refine the result afterward. Not sure what to ask for? A row of example ideas sits under the box. Click one to drop it into the box and edit it from there, or click More ideas to cycle through the rest. As you type, the box also suggests how to finish the sentence, shown in grey ahead of your cursor: press Tab to take the suggestion, or just keep typing to ignore it.
-
Build it by hand. Drag pieces in from the panel on the left onto the canvas and connect them together. The + on a step works both ways: grab it and pull — a line follows your pointer, and wherever you let go is where the next step is created, already connected — or just click it to open a small picker and slot the step in right there. You can drag out of an output dot the same way, and items in the picker can themselves be dragged onto the canvas. Typing in the picker’s search box looks through everything at once — built-in actions, connected apps, and logic steps — so you don’t have to know which tab something lives under. The panel on the left has the same search box at the top: type “loop”, “webhook” or an app’s name and it filters every section — triggers, actions, apps and logic — at once.
-
Ask Champ. From any page, tell the in-app helper what you want (“when someone books, tag them and send a reminder the day before”, “turn the AI back on two hours after I take over a chat”) and he builds it for you. See Asking Champ to build or fix one below.
You can mix all three: start from a prompt or from Champ, then adjust the result on the canvas, or vice versa.
Building with the prompt bar
The prompt bar stays at the bottom of the canvas, so you can keep asking for changes while you build.
- You can stop it. While it is building, the send button becomes a Stop button. Click it and the build ends there, leaving the canvas exactly as it was before you asked.
- It remembers the conversation. Your last few instructions in the same session stay in mind, so a short follow-up like “remove that step” or “make the delay two days instead” is understood without you describing the whole automation again.
- Changes wait for your OK. When you ask the AI to change an automation that already has steps, it no longer replaces your canvas straight away. The proposed version appears on the canvas with new steps outlined in green and changed steps in amber, and a bar at the bottom lists what was added, changed and removed, how many connections changed, and the new name if it picked one. Click Accept to keep it or Reject to put everything back exactly as it was (Cmd+Z or Ctrl+Z rejects too). Until you choose, the automation can’t be saved or switched on. Building from an empty canvas still applies right away, since there is nothing to lose.
- What the AI says stays until you close it. When the AI explains something about what it built (a step it left out, a question it needs answered), that note stays on screen until you dismiss it. It also shows in the review bar next to the changes, and after that a Show the AI’s note button above the prompt bar opens it again until your next request.
- One Undo takes the whole change back. Whatever the AI added or rearranged counts as one change, so after you accept it, clicking Undo in the toolbar once puts the canvas back the way it was.
- It only adds what you asked for. It will not slip in steps that change an account’s credits, block an account, delete things or message people unless you asked for that, so a prompt about tagging contacts comes back as tagging contacts and nothing else.
- It writes in your language. The step labels it puts on the canvas, and the automation’s name, description and notes, come back in the language your app is set to, the one you picked under Settings → Profile → Language. Set the app to French and what the AI writes is in French, without you having to ask for it. Automations you already have are left exactly as they are, so changing your language does not rewrite them: ask the prompt bar to rename the steps, or rename them yourself.
- It names and describes what it builds. A new automation comes back with a name and a short description already filled in, so the Automations list tells you what each one does without opening it. When you ask for a change later it leaves the name and description you have alone, unless you ask it to rename or re-describe the automation, or the change made them wrong. Anything you typed yourself is only replaced when you ask.
Asking Champ to build or fix one
Champ, the helper in the corner of every page, can build an automation for you and change one you already have. Describe what should happen and when, and he looks up the pieces it needs on your account (your agents, tags, lists and event types), puts the trigger and the steps together and saves it.
- What he saves is always a draft, switched off. Nothing runs because of a chat. After he builds or changes one, he tells you in plain words what it will do, what it sends and to whom, and offers to open it on the canvas or to switch it on.
- Switching it on is a separate yes. He only turns an automation on when you tell him to in a later message, after you have seen what it does. Saying yes to building it is not a yes to switching it on. Asking him to switch one off always works.
- He only adds what you asked for, the same rule the prompt bar follows: no extra steps that send, delete, pause or change credits, and no guessed ids. When something is ambiguous (which agent, which tag, how long before), he asks first.
- Fixing one. Paste a run error or tell him which step is wrong (“the reminder step has no message text”) and he changes that step and keeps the rest. If the automation is on, the fix is live straight away; he says so.
- What stays on the canvas. Deleting an automation, running one by hand, and anything that needs an app you connect in the editor (a spreadsheet, your mail server) are done here, not in the chat.
Everything he builds opens in this editor like any other automation, so you can read it, tweak it and switch it on yourself.
Saving your changes
Nothing on the canvas is saved on its own. Every change you make — adding a step, editing a field, moving a node, changing the automation’s settings — stays as a draft in your browser until you click Save at the top right (or press Cmd+S / Ctrl+S). While there is something unsaved, the status next to the button reads Unsaved draft; Discard throws the draft away and puts the automation back to its last saved state.
A live automation keeps running on its last saved version while you work, so you can rebuild half of it without anything half-finished firing for real. Turning the Enabled switch on saves first, because what you switch on is what is on the canvas. If you close the tab or head to another page with unsaved changes, you are asked whether to save, leave without saving, or stay.

After a change the header reads Unsaved draft. Save keeps it, Discard puts the automation back to its last saved state.
Triggers
Every automation starts with exactly one trigger — the event that kicks it off. There are a lot of them now, so the trigger picker sorts them into groups by what they’re about.
Messaging
| Trigger | Fires when… |
|---|---|
| Incoming message | A contact sends a message, on any channel or one you pick — optionally narrowed to messages containing certain words, and to the conversations of one AI agent (or one classic campaign). See Running an automation for one agent only |
| Message delivered | A message you sent is confirmed delivered by the channel. Can be narrowed to one channel and to the contacts of one AI agent |
| Message failed | A message you sent couldn’t be delivered. The run gets the reason the channel gave back, so you can alert someone, try another channel, or tag the contact. A WhatsApp Web message to a number that isn’t on WhatsApp counts too: its reason is “This number is not on WhatsApp” and its error code is not_on_whatsapp, which a Condition step can check. Can be narrowed to one channel and to the contacts of one AI agent |
| Missed call | Someone calls one of your WhatsApp Web numbers, or your connected Twilio SMS number, and you don’t pick up — whether they hang up after a few rings or it rings out. Optionally limited to calls to one of those numbers. The run knows who called, which number they called, which channel it was and whether it was a video call, so a message can go back to them on WhatsApp or by SMS within seconds. See Example: turn a missed WhatsApp call into a chat |
| Follow-up sent | Your agent sends an automatic follow-up to a contact. The run gets which follow-up it was (quick, warm cycle or cold), the message text and the channel, so you can log it in your CRM or notify someone |
| Follow-up skipped | A follow-up was held back because the agent’s send check failed. The run gets what the check saw. See Only Send a Follow-Up When a Check Passes |
| Follow-ups exhausted | A contact has received every follow-up in the sequence without replying. The moment to hand them to a person or move the deal |
| Message sent | A message leaves your account. It fires for every outgoing message, whatever sent it, so use Sent by to narrow it to the AI agent, a person, an automation, a broadcast, the API or an automatic follow-up. Can also be limited to one channel |
| Conversation closed | A chat session is closed. The run gets when the conversation started, when it closed and how many messages it held, so you can log it, score it or report on it. Can be narrowed to one channel and to the conversations of one AI agent |
| Broadcast finished | A broadcast has finished sending. No settings to fill in: the run gets how many messages went out, how many failed and the total |
Contacts
| Trigger | Fires when… |
|---|---|
| New contact | A contact is added to your account — from a conversation, an import, a form, the API, anywhere |
| Contact updated | A contact’s details change — any field, or one specific field you choose. For Tags, Becomes picks one or more of your own tags, so it fires only when the contact gains one of them; for Assigned to, it picks one or more of your team members, so it fires only when the contact is assigned to one of them |
| Contact added | You add contacts to it yourself — in bulk from Contacts, from one contact, from a conversation, or from the automation itself. One run per contact. See Adding contacts to an automation |
| Tag applied | A tag is added to a contact. Narrow it to one tag (pick it from your tags, or choose Type a name instead for one your AI agent will create later), to one channel, and to who applied it: your AI agent, a person, an automation, the API or an import |
| Tag removed | A tag is taken off a contact. Narrow it to one tag (picked from your tags or typed) and to one channel |
Deals
| Trigger | Fires when… |
|---|---|
| Deal updated | A deal’s details change — any field, or one specific field you choose (its stage, for example). For Assigned to, Becomes picks one or more of your team members |
| Deal created | A new deal is added to one of your pipelines. Can be narrowed to one pipeline and one stage |
| Deal stage changed | A deal moves to a different stage, however it moved: dragged on the board, moved by an automation, moved by a tag rule, or moved by the idle rule on the stage itself. The run names the stage it left and the one it entered. Can be narrowed to one pipeline, to deals moving out of a stage, into a stage, or both |
Appointments
| Trigger | Fires when… |
|---|---|
| Appointment booked | A new appointment is booked |
| Appointment cancelled | A booked appointment is cancelled — the cancellation reason comes along with it |
| Before an appointment | A set time before each confirmed appointment, for reminders. Pick the moments you want — 24 hours before, 3 hours before, or your own number of minutes — up to five per automation. The reminder fires at exactly that moment, whatever the local time. If an offset could land in the middle of the night for some contacts, switch on Respect quiet hours in Automation settings and the message waits until 8 AM their time — see Respecting quiet hours and Example: appointment reminders |
| Appointment rescheduled | A booked appointment moves to a different time. The run gets the previous start and end next to the new ones, so a message can tell the contact exactly what changed. Can be limited to one appointment type |
Tasks
| Trigger | Fires when… |
|---|---|
| Task created | A task is created — optionally only one kind of task, like a human alert, a knowledge-base gap, a follow-up, or one of your own task types |
| Task completed | A task is moved into a completed stage |
Account
| Trigger | Fires when… |
|---|---|
| Low credit balance | Your credit balance drops below the alert threshold set in your account. It fires at most once a day, and re-arms after you top up |
| Channel connected | One of your channels finishes connecting, such as a WhatsApp number pairing or an Instagram account linking. Can be limited to one channel |
| Channel disconnected | One of your channels drops: logged out, unlinked, or cut off by the provider. The moment to alert yourself, before messages start failing. For a WhatsApp Web number, a logout or unlink fires right away; a short drop that reconnects on its own does not count, and fires only if the number is still down 30 minutes later. trigger.reason says which: logged_out, blocked_by_whatsapp or not_reconnected. Can be limited to one channel |
Apps
| Trigger | Fires when… |
|---|---|
| App event | Something happens in an app you connect: a deal stage changes in HubSpot, a payment comes in on Stripe, a form is submitted in Typeform, a row is added to a Google Sheet. Pick the app, then the event. Everything the app sends about the event is available to later steps. See App events |
Agency
| Trigger | Fires when… |
|---|---|
| Sub-account created | A client account is created under your agency — from your Sub Accounts page, over the API, or through your own signup page. Which of the three it was comes along with the run, as created_via |
| Sub-account activity | Something happens on one of your client accounts. Pick the event you care about: credits low, credits exhausted, channel connected, channel disconnected, blocked, unblocked, plan changed, plan cancelled, subscription started, resubscribed after cancelling or deleted. Leave it on Any event and the automation runs for all of them |
Both of these live on your agency account, not inside the client’s — build them once and they cover every client you have, including the ones you add later. The client account’s details come with the run like any other trigger data: ${trigger.sub_account.id}, ${trigger.sub_account.email}, ${trigger.sub_account.business_name}, ${trigger.sub_account.credits}, ${trigger.sub_account.created_via} and the rest of the account’s fields — insert them with the + button rather than typing them. Sub-account activity also hands you the event itself (${trigger.event}) and whatever that event carries, such as the credit balance that set it off. Pair them with the Update sub-account action below: Automate what happens to client accounts has the recipes.
Which plan event? There are four, and the narrow ones exist so a run only starts when there is something to do. Subscription started fires when a client goes from no plan to a live one: a first subscription, a trial starting, or a client coming back after cancelling. Resubscribed after cancelling fires only for that last case, a client whose plan was cancelled subscribing again, and it fires together with Subscription started, so pick one of the two for an automation, not both. Plan cancelled fires only when a client cancels their plan, or when their trial ends without a subscription starting. None of the three reacts to a renewal, a switch between plans, a trial turning into a paid plan, or a failed payment that recovers. Plan changed is the broad one: it fires whenever the plan or its status moves, which includes every start, every cancellation and every switch, so two automations on Plan changed that are meant for opposite cases (one for leaving, one for coming back) both run on the same cancellation. Put each on its own narrow event instead and they can never collide, and you stop paying for runs a Condition step throws away. All four carry the plan name and the subscription status, plus what they were before the change: ${trigger.previous_plan_name} and ${trigger.previous_subscription_status}, empty when the client had no plan. A trigger left on Any event reacts to a plan move once, through Plan changed; the three narrow events only start an automation that picks them by name, so nothing runs twice.
Credits low: choose your own line. Pick Credits low as the event and a Low-credit threshold field appears. Leave it empty and the event fires when a client’s credits drop below the threshold of their automatic top-up, or below 10 when they have none. Enter a number and this automation fires when the client’s credits drop to that number or below it, coming down from above. Each automation keeps its own number, so one can warn you at 500 and another at 50. The run carries the balance before the drop (${trigger.previous_credits}), the line that was crossed (${trigger.threshold}) and whether the client has automatic top-up switched on (${trigger.auto_top_up_enabled}, true whether you pay for their top-ups or they use their own card). Credits exhausted carries ${trigger.auto_top_up_enabled} too. In a Condition step, the Credits before and Auto top-up on presets filter on these, for example to alert only the clients whose account will not top itself up.
General
| Trigger | Fires when… |
|---|---|
| On schedule | A recurring time you set (for example, every morning at 9am) |
| Webhook | An outside tool or website sends data to a web address the automation gives you. It can send JSON or a classic form post (the format many payment providers and form tools use) — either way, each field it sends is available to later steps as ${trigger.field_name}. Anything added to the end of the web address also becomes a field: …?phone=15551234567 gives you ${trigger.phone}. That’s the way in for form builders that can’t change the shape of what they post but can insert an answer into the address (Paperform’s answer piping, for example: …?phone={{ your_phone_question_key }}) |
| AI Agent Function | Your AI agent calls the automation itself, mid-conversation, as one of its abilities — see the next section |
| New feed item | A new item appears in an RSS or Atom feed you point it at — checked every few minutes. Turning the automation on doesn’t fire it for items already in the feed, only for new ones from then on |
| Email received | An email arrives in your own mailbox. Connect the mailbox once (your provider’s IMAP details — server address, username, password; if you use two-step sign-in, use an app password). You can narrow it to emails whose sender or subject contains certain words |
| Manual run | Only when you click Run yourself — useful while you’re still building and testing |
Triggers react to your whole account, not just to the builder. Incoming message, Contact updated and Deal updated fire wherever the change came from: your AI agent updating a contact mid-conversation, a broadcast, someone editing a record on screen, an import, or your own software calling the API. You don’t have to do anything in the automation for that — it’s simply how they work now.
Picked the wrong one, or changed your mind later? Open the trigger and click Change trigger to switch it to a different kind — the rest of your automation stays exactly as it is. If the current trigger already has settings you’ve filled in, you’ll be asked to confirm before they’re cleared.
App events
The App event trigger starts an automation from something that happens in another app you use. There are 41 apps to choose from today, among them HubSpot, Pipedrive, Salesforce, Close, Stripe, Shopify, Calendly, Typeform, Google Sheets, Google Drive, Google Calendar, Gmail, Outlook, Slack, Discord, Trello, ClickUp, Asana, Monday, Jira, Linear, Notion, Airtable, Zendesk, Zoom, Mailchimp, MailerLite, Kit, DocuSign and GitHub. The picker only lists apps that can report events.
Setting it up
- Open the trigger and pick App event under Apps. (Already have another trigger? Click Change trigger first.)
- Under App, choose the app. Under Event, choose what has to happen in it for the automation to run once.
- If the app is not connected yet, connect it right there, the same way you connect an app for an action step. Under Account, the automation shows which connected account it listens on.
- Fill in Event settings, if the event has any. These are the details the app needs to know which events to send, and the required ones are marked. Some events ask for details from the app’s own developer settings. Where that is the case, How to set this up in the app under the event explains where to find them.
- Save the automation and turn it on.
Is it listening? Under the settings the trigger tells you where it stands. Listening means events from the app start the automation. Paused with the automation means the automation is switched off: turn it back on and it listens again. Not listening comes with the reason the app gave, for example that the connected account was removed. Pausing the automation stops the events. Deleting it, or switching the trigger to another app or event, removes the old listener. Disconnecting an app’s account stops every automation that listens on that account, and their triggers show why.
Some apps report events a few minutes late. Not every app pushes an event the moment it happens. For those, the event is checked for every few minutes (the interval in Event settings, in minutes), so a run can start a little after the event itself. The trigger shows a note when the event you picked works this way.
Using what the app sent. Every field the app sends about the event is available to later steps as ${trigger.field_name}. Next to those, ${trigger.app_event.toolkit} is the app, ${trigger.app_event.event} the event, ${trigger.app_event.id} the id of this delivery and ${trigger.app_event.received_at} when it arrived. The whole delivery, untouched, sits under ${trigger.raw}. The sample in the + picker starts out with what the event usually contains. Once a real event has come in, click Use the last real event as sample and the picker shows exactly the fields your app sends.
What it costs. Each run costs the same as a run started by any other trigger (see What automations cost). The run history labels these runs App event.
Events an app only sends to developer apps. A few events can’t be switched on from a normal app connection, because the app only delivers them to a developer app. Today that is HubSpot’s Contact created and Deal stage updated. They show greyed out in the event list with Not available; hover the label to see why. To react to new HubSpot contacts or deal changes, use a Schedule trigger (every hour, for example) with a HubSpot search step that finds the deals or contacts that changed since the last run, and a Loop over what it finds.
Automation settings
Some choices belong to the automation as a whole rather than to one step. They live behind the gear icon at the top right of the editor, in Automation settings, and they are part of the draft like everything else — click Save for them to take effect. There are five:
- Description: a note about what this automation does, shown under its name in the list.
- Allow re-entry — whether a contact can go through this automation more than once.
- Stop on response — end a contact’s run the moment they message you.
- Respect quiet hours — hold messages that would go out at night in the contact’s local time.
- Only run during these hours — ignore the trigger outside a window you set.

Click the gear icon, Settings for the whole automation, to open Automation settings: the description plus Allow re-entry, Stop on response, Respect quiet hours and Only run during these hours.
Saying what an automation does
A name like “Missed call text-back” tells you enough; “Follow-up 3” a month later does not. The Description box at the top of Automation settings is free text for exactly that: write a line or two about what the automation does, who it is for, or why you built it.
What you write shows under the automation’s name on the Automations list, so you can read down the page and see what each one is for without opening it. The search box on that page looks through descriptions as well as names, so “restaurant” or “reminder” in a description is enough to find the automation again. It is optional, it changes nothing about how the automation runs, and leaving it empty keeps the list exactly as it was.
Letting a contact go through it more than once
Allow re-entry decides what happens when the trigger fires again for someone who has already been through the automation.
- Off: each contact goes through the automation once. The next time the trigger fires for them — they send another message, book another appointment, get the same tag again — nothing starts. The run history stays quiet for them, the same way it does for a message that doesn’t match the trigger’s filter. Anyone who has ever had a run of this automation counts as having been through it, whether that run finished, failed, or was stopped.
- On: a contact can enter again every time the trigger fires. This is the setting for anything recurring — appointment reminders, booking confirmations, a keyword that should get the same reply every time.
The default depends on the trigger. For Contact added (people you add from the Contacts page) it is off, so adding the same list twice never double-messages anyone. For every other trigger it is on, which is how automations have always behaved — nothing you built before this setting existed changes on its own.
Two things to keep in mind. Re-entry is about the contact, so triggers that don’t carry one — On schedule, Webhook received, RSS, Email received — aren’t affected either way. And the three appointment triggers (Appointment booked, Appointment cancelled, Before an appointment) always allow re-entry, whatever the switch says: they fire once per booking, and a reminder trigger fires once per reminder time, so a per-contact “once” would skip a returning customer’s next booking and even the second reminder for the same one. The switch is greyed out for those.
Stopping when a contact replies
Stop on response is for follow-up sequences: a run that is waiting in a Delay, or working through its steps, ends the moment the contact sends you a message on any channel. Their run shows as Cancelled in the run history; nobody else’s run is touched, and the automation stays on for everyone. When Stop on response ends a run, its detail page says the contact replied, while a run you cancel yourself says it was cancelled by hand.
It is off by default. When it’s on and the automation’s own trigger is Incoming message, the reply that stops one run can start a fresh one if the trigger matches it and re-entry allows — the same way a follow-up sequence would restart in most CRMs. Turn re-entry off too if you want each contact to get the sequence once.
Respecting quiet hours
An automation runs the moment its trigger fires, and that moment isn’t always a polite one — an appointment reminder set for 12 hours ahead lands at 2 AM for anyone with an early-morning slot, and a contact on the other side of the world is asleep when you’re not.
Respect quiet hours is a per-automation switch for exactly that. Where to find it: click the gear icon at the top right of the editor to open Automation settings — it’s there whatever kind of trigger the automation has.
It’s off by default, on new and existing automations alike, so nothing you’ve already built changes behaviour on its own.
When you switch it on, for that automation only:
- Message steps that would go out between 8 PM and 8 AM in the contact’s local time wait and are sent at around 8 AM their time instead — a short random delay spreads them over 8:00–8:15 rather than firing all at once. That covers Send message, WhatsApp template and WhatsApp Web send steps.
- Every other step still runs right away. Tags, conditions, delays, webhooks, updating a contact, creating a task — none of it is held back. Only the message itself waits.
- Message steps inside a Loop are the one exception — they send right away even with the switch on: holding each contact’s message separately would smear one loop across the whole quiet window. Put the message after the loop if it needs to wait for morning, or use Only run during these hours on the trigger so the whole loop runs at a polite time.
- The trigger’s own timing doesn’t change. A “3 hours before the appointment” reminder still runs three hours before; if that lands at 3 AM, the run happens and the message is what waits until morning.
- Local time means the contact’s time, not yours. It’s worked out from their phone number’s country code, or a timezone saved on the contact — the same way the account-wide Quiet Hours setting does it.
This is separate from the account-wide Quiet Hours setting in Settings → Profile, which covers follow-ups and AI-scheduled sends. That one doesn’t reach into your automations, which is why each automation carries its own switch. See Quiet Hours & Compliance for the account-level side.
Building a reminder for a fixed time of day? If the message only ever goes out during working hours anyway, leave the toggle off — it costs you nothing, but there’s no reason to add a hold that will never be used.
Only running during certain hours
Quiet hours holds back the messages; every other step still runs. Sometimes that isn’t what you want — sometimes the whole automation should stay off outside a window. Say it hands chats to your team, and your team is only in from 9 to 6: at 2 AM you don’t want the hand-over delayed until morning, you want it not to happen at all.
Only run during these hours is a second per-automation switch for exactly that. Where to find it: open Automation settings (the gear icon at the top right of the editor) — it sits right under Respect quiet hours, whatever kind of trigger the automation has. Switch it on and set a start time, an end time, and a timezone.
- Inside the window the automation behaves exactly as before.
- Outside the window the trigger is simply ignored. The automation doesn’t run, nothing is queued for later, and nothing shows in the run history — the event is treated the same way as a message that doesn’t match the trigger’s text filter. If overnight events should still be handled eventually, this switch is the wrong tool; leave it off and use Respect quiet hours instead.
- End before start means an overnight window. 21:00 to 08:00 runs through the night and stays off during the day.
- The window uses the one timezone you set on the automation — not each contact’s local time. Quiet hours is per-contact; this is one clock for the whole automation. Type the timezone the way the On schedule trigger takes it, e.g.
Europe/LondonorAmerica/Lima. - On schedule triggers are checked at the moment they fire. A scheduled run whose moment lands outside the window is skipped, not moved.
The difference in one line: Respect quiet hours runs the automation and holds only its messages until morning; Only run during these hours doesn’t run the automation at all.
And if what you actually want is one automation that behaves differently by time — one thing during the day, another at night — don’t skip the run: branch it with a Condition step set to Time of day (see Steps).
Running an automation for one agent only
Most accounts run more than one AI agent, and an automation that should only apply to one of them — the support agent, say, and not the sales one — needs a way to say so. Four triggers have a field for exactly that:
| Trigger | The field |
|---|---|
| Incoming message | Agent (optional) |
| Conversation closed | Agent (optional) |
| Message delivered | Agent (optional) |
| Message failed | Agent (optional) |
Open the trigger, click the field, and you get a grouped list: your AI agents by name, and your classic campaigns underneath if your account still has any. Pick one and the automation only runs for contacts that agent is responsible for; every other conversation on your account is ignored. Leave it on Any agent, which is how it starts, and the automation runs for every contact on the account, including contacts no agent has been assigned to.
It reads the agent the contact is assigned to at that moment, so moving a contact to another agent today changes which of these automations run for them from then on.
The field is one choice, not a set — an automation is narrowed to a single agent or a single campaign, so build a second automation if you want the same steps on another one.
Every other trigger runs for the whole account. There is no agent field on the contact, deal, appointment, task, account or general triggers: they fire for everything in the account. To narrow one of those to a single agent, add a Condition step as the first step after the trigger and check the contact’s assigned agent, then put the rest of the steps on the true path. See Steps.
Not every agent can be narrowed to yet. Any agent the field can’t offer is counted just below it, so you can see at a glance that the list is short rather than wondering why an agent is missing. Those conversations still work normally; they just can’t be singled out here for the moment.
One more thing worth knowing, on accounts using AI agents: a message-triggered automation narrowed this way fires on a brand-new contact’s very first message as well as on every message after it. It used to start from their second message, so the opening message of every new conversation slipped past it. (This is about automations whose trigger is an incoming message — it’s separate from the Contact added trigger above, which runs exactly once per contact you feed in.)
Letting your AI agent call an automation
The AI Agent Function trigger turns an automation into an ability your AI agent can use while it’s talking to a customer — the same way it already uses custom functions. The customer asks something, the agent decides your automation is the right tool for it, calls it with the details it collected from the conversation, and (if you want) gets an answer back to use in its very next reply.
Setting one up:
- Name the function. A short name in letters, numbers and underscores —
check_availability,register_warranty. The AI sees this name, so make it say what it does. - Describe when to use it. The description is how your agent decides to call it — write it the way you’d brief a new team member: “Use this when a customer asks whether we have an appointment slot free on a given day.”
- Add the details to collect. Each parameter is one piece of information the AI should gather from the conversation before calling — a city, an order number, a preferred date. Give each one a name, a type and a short description; mark the ones that are required. The type can be text, a number, a yes/no, or JSON — pick JSON when the AI should hand over a structured bundle of fields (say, a full delivery address) rather than a single value.
- Pick which agents can use it. Choose the AI agents that should have this ability — either here on the trigger, or later from any agent’s AI Abilities tab, where the function appears alongside the agent’s other abilities with a normal on/off toggle. Both places edit the same thing, so use whichever you’re already in.
- Turn the automation on. From that moment, those agents have the function — nothing to copy anywhere, no webhook addresses or secrets to paste around.
Don’t feel like writing the name, description and details yourself? Build the automation’s steps first, then click Fill in with AI at the top of the trigger’s settings — it reads what your automation does and writes them for you. Anything you’ve already typed stays as it is; it only fills in what you left empty. Review the result, tweak what you like, and save.
Inside the automation, everything the AI sent is available through the usual data buttons: each parameter under trigger.args, plus which contact and channel the conversation is on.
Answering the agent. Add a Return response step and whatever it sends back becomes the answer the AI reads — so it can quote real data in the same conversation turn: look up stock in your own database, check a calendar, calculate a quote. Without a Return response step, the agent waits for the automation to finish (up to 25 seconds) and is told whether it worked: finished successfully, or failed. That is right for “register this complaint in my system”-style work that doesn’t need data back. If the automation is still going after 25 seconds, or is waiting on a long Delay step, the agent is told it is running in the background and carries on. One thing to keep in mind: the agent waits up to 25 seconds for a reply, so keep Delay steps out of the path between the trigger and the Return response step. If the run fails before it reaches the Return response step (a step errors, or your balance can’t cover the run), the agent is told the call failed, alerts a human and tells the customer there was a technical issue. It never promises an answer that isn’t coming. The same happens when the Return response step itself sends an error status (400 or higher), so send a 200 with a clear message in the body when “not found” is an answer you want the agent to relay.
While the automation is switched off, agents can’t call it — the function disappears from their abilities until you turn it back on.
You’ll also notice the function listed on your Custom Functions page with a “Managed by automation” badge. That entry is looked after for you — its name and fields follow whatever you set on the trigger — so it can’t be edited or deleted there; open the automation instead.
Adding contacts to an automation
Most triggers wait for something to happen. The Contact added trigger is the one you drive yourself: you pick the contacts, and the automation runs once for each of them. It’s how you build a follow-up sequence, a welcome series, or a re-engagement push — message, wait, message again — and then feed people into it whenever you like.
Build it like any other automation: give it the Contact added trigger, then add your steps. Everything about the contact is available to those steps through the usual data buttons — their name, phone, email and channel — so a Send message step can greet them by name, and it already knows which contact to send to.
There are four places to add people, so you can do it from wherever you already are:
From Contacts, in bulk. Go to Contacts, tick the contacts you want — one, a handful, or everyone on a filtered list — then click Automation in the bar at the bottom. Pick the automation and click Add contacts. Only automations with the Contact added trigger appear, and one that’s still paused is greyed out until you turn it on.
From one contact. Open a contact to bring up their details panel and click Add to automation.
From a conversation. In Chats, open the three-dots menu at the top of the conversation and choose Add to automation — handy when you’re mid-reply and realise this person should go into your follow-up sequence.
From the automation itself. This is the one to use when you’re looking at an automation and thinking “who goes in here?”. On the Automations list, a Contact added automation that’s switched on has an add-person icon in its row; click it and search your contacts by name, phone or email, tick the ones you want, and add them. The same button sits at the top of the automation’s Added contacts panel on its Log page.
Whichever route you take, the automation starts running for those contacts and you can carry on working.
Adding gradually (drip). Adding a few hundred people at once means a few hundred messages going out in a short window, which is rarely what you want — especially on WhatsApp. Tick Add gradually in the same dialog and set how many contacts to add at a time and how many minutes to wait between batches: 20 contacts every 30 minutes spreads a 500-person list over about half a day. Whatever you choose, contacts are always fed in steadily rather than all at once, so a large batch can’t overwhelm your account.
Watching progress. Open the automation and click Log. Above the run history, the Added contacts panel shows each batch you’ve added, how many contacts have been processed so far, and buttons to Pause, Resume or Cancel it. Pausing stops new contacts being added; runs already started finish normally. Cancelling stops the rest for good — it can’t be resumed.
Adding the same person twice. By default each contact can only ever go through a given automation once: add them again later and they’re quietly skipped, counted as “skipped” in the progress line. If you want a contact to be able to go through it again — a monthly check-in, say — open Automation settings (the gear icon at the top right) and switch on Allow re-entry. See Letting a contact go through it more than once.
Two things worth knowing: contact details are taken at the moment you add someone, so editing a phone number afterwards doesn’t change a run that’s already queued; and if you switch the automation off while contacts are still being added, the batch pauses instead of failing — turn it back on and click Resume.
Steps
After the trigger, add as many steps as you need:
-
Actions — do something in DM Champ: message a contact, edit their details, tag them, move them between lists, hand them to another AI agent, create and update tasks and deals, book, move or cancel appointments, look things up to use later in the workflow, or alert a human. The full list is in Actions below.
-
Integrations — connect an outside app (Google Sheets, Slack, and others) and use its actions inside your automation. Connect it once from the builder, then drag it in like any other step. If a step uses an app you haven’t connected yet, the step shows a small amber dot on the canvas and its settings panel shows a Connect button right where you need it — click it, approve the app in the tab that opens, and the step unlocks on its own. This also covers automations the AI builds for you: any step that still needs an app connection tells you so before you turn the automation on.
Every action you’ll find under an app’s Popular heading comes with a guided form instead of technical fields. Adding a row to Google Sheets, for example, walks you through it: pick one of your spreadsheets from a list, pick the sheet, and then each of your sheet’s own column headings appears as its own field to fill in — with the usual data buttons for inserting values from earlier steps. Finding a row works the same way: pick the spreadsheet and sheet, type what to search for, done. The same treatment covers Gmail (send, draft, reply, find emails), Slack (channels come from a live list), Notion (pick a database and each of its own properties appears as a field), HubSpot (contacts, deals, companies, tickets), Google Calendar (pick a calendar from your own list when creating or finding events), Google Docs (pick a document from a list) and Telegram. Anything unusual sits behind Show advanced options with sensible values already set. Steps set up before this existed keep working as they are; open one and choose Switch to simple mode whenever you want the guided version.
Every other action shows one field per setting the app asks for, labelled in plain words, with the i next to a label explaining it. A setting that holds several values is a small form, not a box of code: a list (the records a new HubSpot note is linked to, say) is a set of rows you add with Add and remove with the x, fixed choices are dropdowns, and a set of named values is name and value rows. Every box takes values from earlier steps with the + button. If you prefer typing the raw values, Edit as JSON next to the field shows the same thing as text, and what you change there shows up in the form.
Use Test step inside any integration step to run just that step for real — for the Sheets example, the row actually appears in your spreadsheet, so you know the automation works before you turn it on.
To change which account an app uses, open any step of that app. Once it is connected, the top of the settings panel shows the connected account (by name or email when the app shares one) with Disconnect and Use another account. Use another account disconnects the current one; then click Connect and sign in with the other account. The connection belongs to your whole workspace, so every automation that uses that app switches to the new account, and steps that use it stop running while nothing is connected.
-
Email (your mail server) — send an email from your own mail server, rather than through Gmail. Pick it as the step type and fill in your provider’s sending details once: server address, port, username, password, and the address you want mail to come from. You’ll find these in your email provider’s settings, usually under “SMTP” or “Sending”. We check the details against your mail server before saving, so if something is wrong you find out immediately rather than the first time the automation runs.
Two things worth knowing. Use port 587 — it’s encrypted, nearly every provider supports it, and it’s the port that works from our sending network. And if your email account uses two-step sign-in, create an app password in your provider’s account settings instead of typing your normal password.
Once connected, the step is just To, Subject and Message, with the usual buttons for inserting data from earlier steps. Cc and Bcc are there too if you need them. Your password is stored encrypted and is never shown back to you — reconnecting asks for it again.
-
Built-in apps — a few tools have their own first-class steps, separate from the integrations catalog:
- Mollie — create a payment link or check whether a payment was paid. Connect it once with your Mollie API key (Mollie Dashboard → Developers → API keys).
- WooCommerce — look up a customer or order in your store, move an order to a new status, or create a coupon code. Connect it with your store’s address plus a REST API key (WooCommerce → Settings → Advanced → REST API → Add key).
- WordPress: create, update or fetch a post, create a user, or find a user by email. Connect it with your site’s address, your WordPress username and an application password (Users → Profile → Application Passwords). See WordPress.
- FluentCRM: create or update a contact, find one by email, add or remove tags, and add someone to lists. Same connection details as WordPress, because FluentCRM runs on your WordPress site. Tags and lists are given as ids, not names. See FluentCRM.
- MemberPress: get a member, find one by email, create a member, list their subscriptions or transactions, and create a transaction, which is how a membership is granted. Connect it with your site’s address plus the API key from MemberPress → Developer Tools. See MemberPress.
Connecting works the same way as the email step: the details are checked live against the service before anything is saved, keys are stored encrypted and never shown back to you, and every step gets plain fields with the usual insert-data buttons.
-
Database query — for technical users: run a SQL query against your own external MySQL or Postgres database (look up a customer in your shop’s database, for example). Add a connection once — it’s tested live before saving — then write the query. Use $1, $2 (Postgres) or ? (MySQL) placeholders for values that come from earlier steps, and put those values in the Values field, so contact-typed text never ends up pasted into your SQL. The database must be reachable from the internet.
-
HTTP request — call any external web address directly, for tools that don’t have a built-in integration yet.
-
Condition — branch the automation down one of two paths depending on a rule you set. Insert the thing you want to check with the + button rather than typing it, pick how to compare it (equals, contains, is greater than, matches regex…), and type what to compare it against. Contains looks for the exact text you typed; when you need a pattern instead — several spellings of a keyword, a word only at the start of a message, an order number format — pick matches regex and type a regular expression such as
^(ja|yes)\b. Add/istyle flags by writing the pattern as/ja|yes/i. A pattern that isn’t valid fails the step with an error in the run history rather than quietly taking the false path. Steps on the true path run when the rule matches, steps on the false path when it doesn’t; a path you leave empty simply ends the run. Checking someone’s tags is one of the most useful ones — insert the contact’s tag_names and use contains with the tag’s name, as in Example: ignore anyone you tag as spam below. To check that someone does NOT have a tag, pick does not contain instead (written asnot containsin the expression).Checking more than one thing. A Condition can hold several rules at once. Set Match to All of the following (every rule has to be true) or Any of the following (one true rule is enough), and use Add condition for each extra rule — for example country equals NL and message contains pricing. If you need to mix the two, or group rules with brackets, type the rule as an expression instead:
(${trigger.contact.country} == 'NL' or ${trigger.contact.country} == 'BE') and ${trigger.message.body} contains 'pricing'—andbinds tighter thanor, and brackets override that. A condition written that way opens as an expression box rather than the rows.
Two rules in one Condition. With Match on All of the following, both have to be true for the Yes path to run.
Stages are compared by their ID, not their name. A task’s or deal’s stage arrives as its internal ID (
todo,in_progress,done…), which can differ from the column title on your board. So when the field is the task’s or the deal’s stage and the comparison is equals or does not equal, the value box becomes a list of your own stages: pick the column by its name and the step stores its ID. A condition saved earlier with a stage name typed in is flagged with a warning under the list, and when the text matches one of your columns a button swaps it for that column’s ID.Other values that point at your account are lists too. With the contact’s tags (contains, equals), the tag a Tag added trigger carries, a deal’s or task’s assignee, the AI agent, or a custom field of the Dropdown type, the value box is a list of your own tags, team members, agents or the field’s options. Click Use a value from an earlier step instead to compare against a value from the trigger or another step.
Every next step needs a branch. A step connected to a Condition has to hang off its Yes or No handle. One that is connected without a branch runs whichever way the condition answers — the editor flags it and won’t let you turn the automation on until it is moved onto a handle.
A Condition can also branch on the clock instead of a value. Set its Condition type to Time of day and give it a start time, an end time and a timezone: the true path runs while the current time is inside that window, the false path outside it. End before start makes an overnight window (21:00 to 08:00), and the Days toggles limit it to certain days of the week — leave them all off for every day. It checks the clock at the moment the step runs, so a time condition placed after a Delay looks at the time it’s actually reached, not the time the run started. This is how you build “one automation, different behaviour by time” — do one thing during the day and another at night; when instead the automation simply shouldn’t run at all outside a window, use Only run during these hours in Automation settings.
In a normal Compare a value condition you can also compare against the clock directly: the Current time group in the insert-data picker offers
now.hour(0–23),now.minute,now.weekday(1 = Monday … 7 = Sunday),now.day,now.monthandnow.year. They’re read in UTC unless you fill in the condition’s optional timezone field. -
AI step — have the built-in AI read the data so far and generate a response or decision as part of the workflow. Write a prompt, insert values from earlier steps, and the step’s output is available to every step after it. There’s nothing to configure beyond the prompt — the AI itself is managed for you. The step’s settings say the price up front: each time an AI step runs it uses 0.25 credits (so an AI step inside a Loop uses 0.25 credits per repeat), and Test step runs the real AI, so it uses the same 0.25 credits.
Two limits worth knowing, both generous enough that most automations never meet them. Replies have a maximum length; if the AI needs more room than that, the answer is cut off — you’ll see a note saying so when you test the step, so ask for something shorter or split the work across two AI steps. And the prompt itself has a maximum size once the data from earlier steps is filled in: if you insert a very large amount of data (a long chat history, a whole scraped page), the run stops with a message telling you to pass in less. And while Pause all AI messages is on in Settings → Profile, an AI step does not run at all: the run stops with a note that AI is paused for the account, and nothing is charged. Turn the pause off and new runs go through again.
-
Delay — pause before continuing. Wait type offers two ways to do that. For a fixed amount of time is the classic one: wait 10 minutes, 2 hours, 3 days, with an optional bit of random jitter so consecutive runs don’t all fire on the same second. Until a specific moment waits for a date and time instead — usually one you insert from an earlier step with the + button, like the appointment’s start time — and an Offset in minutes shifts it:
-180means three hours before that moment,-1440a day before,0the moment itself. If the moment has already gone by the time the run reaches the step, it doesn’t wait at all and simply carries on; waits longer than 30 days are refused. Waits of more than half a minute pause the run properly rather than holding it open — the run shows as waiting until it’s time, so minutes, hours and days are all fine. -
Loop — repeat a group of steps once for each item in a list (for example, once per contact that Find contacts returned, or once per tag on a contact). Leave Max iterations blank to go through every item, up to 1,000; set a number to stop earlier. A long list doesn’t have to fit in one go: when a run is close to its time budget the loop pauses where it is and picks up again a few seconds later from the same item, so a daily sweep over several hundred contacts finishes on its own. A Delay inside the loop works the same way — the loop waits it out and carries on with the next step for that item. Connect the steps to repeat to the loop’s body handle and stop there: a branch that simply ends is how the loop knows that item is finished, and it moves on to the next one by itself. A Condition inside the loop decides per item: only that item’s true (or false) branch runs, so Loop → Condition → Send message sends only to the items that pass. You don’t need a line back to the Loop, and the canvas no longer lets you draw one: pull a connection from a later step back into the Loop (or into any step above it) and the line is refused with a note saying why. If an automation you built earlier still has one, its first run pauses it: the automation is switched off, the list shows Paused automatically (hover it for the reason) and the editor names the connection to remove. Remove it, save, and switch the automation back on.
-
Return response — for automations that start with a Webhook or AI Agent Function trigger: send data back to whatever called the automation — the outside tool that hit your webhook, or your own AI agent mid-conversation. By default a call just gets an acknowledgement; add this step and the caller receives your own reply instead — pick a status code, write the body (JSON or plain text) and insert values from earlier steps, so the tool that called you gets, say, the row you looked up or the contact you created. The caller waits up to 30 seconds; if the automation takes longer than that (a Delay step upstream, for example), it falls back to the normal acknowledgement and the automation carries on regardless. If the run fails before it gets to this step, the caller gets an answer straight away instead of waiting: status 200 with
"status": "failed"in the body (andinsufficient_creditsas the error code when your balance couldn’t cover the run). It is deliberately not an error status: the request was received and earlier steps may already have run, and tools like Stripe or Shopify re-send a webhook that gets an error back, which would run those steps again. The details stay in the run history. Test step shows a preview of the reply with your sample data.
There’s also a Transform step for reshaping data with a bit of code — this one’s for technical users comfortable writing a small script; everyone else can safely ignore it.
Using what an earlier step returned
When a field asks for one value, such as Contact ID, insert that one value with the + button, not the whole step. After a Find contact step called find_contact, that is ${nodes.find_contact.contactId}. Inserting ${nodes.find_contact} on its own passes everything the step returned at once, and a step that needs a contact then fails with “contact not found”.
Expressions
Inside ${ } you can write a small bit of JavaScript to change a value before it is used. Write it in any field that takes variables, with the same names the + button inserts:
| You want | Write |
|---|---|
| A name in capitals | ${ trigger.contact.first_name.toUpperCase() } |
| A phone number without the + | ${ trigger.contact.phone.replace("+", "") } |
| An amount with 21% added | ${ trigger.amount * 1.21 } |
| One word or another | ${ trigger.amount > 100 ? "priority" : "normal" } |
| Today’s date (in UTC) | ${ new Date().toISOString().slice(0, 10) } |
Text around it stays as it is, so Hi ${ trigger.contact.first_name.toUpperCase() }! sends “Hi ADA!”. The Result box under the field shows what the code works out to with your sample data while you type.
If the code fails (a typo, or a field that is empty for this contact), that part comes out empty and the rest of the step carries on. The run history says which bit of code failed and why.
The code runs instantly and on its own: it has no internet access and cannot wait for anything, and it may take at most half a second. One bit of code inside ${ } can be up to 16,000 characters long; longer code is treated like code that fails, and the run history says it is too long. To fetch something, use an HTTP request step and insert its result. When the logic needs more than one line, or several steps share the same result, a Transform step is still the better tool.
When a step fails
By default a step that fails stops the automation, and the run history shows the step in red with the reason. Two switches let it carry on instead:
- If this step fails, keep going, in any step’s settings. The automation goes on with the next step, and the failed step’s result has
failedset to true anderrorholding the reason, so a Condition on${nodes.<step>.failed}can do something only when it failed: alert yourself, try another channel, tag the contact. The run counts as finished, with a Kept going after an error note on it, and the failed step still shows in red. - If one item fails, skip it and go on with the next, in a Loop’s settings. One item that fails no longer stops the whole list: that item is skipped, the rest still run, and the loop’s result lists the skipped items under
failed_items. Useful for a sweep over many deals or contacts, where one bad record shouldn’t hold up the others.
Running out of credits always stops the automation, whatever these switches say. An HTTP request step that gets an error status back (a 404 or a 500) has not failed: it finished and hands the status on, so check its status or ok with a Condition to act on it.
Testing steps that look up a contact
Run and Test step use the trigger’s sample data, and that sample is a made-up contact (contact_abc123, [email protected], with no phone number). It does not exist in your account, so a step that looks up or messages a contact fails in a test with “contact not found” or “no number stored”. That is expected: when a real trigger fires, the step gets the real contact and works. To test with real data, let the automation run once for real, then click Replay in the toolbar to run it again with what that last run actually received.
Actions
Actions are the things an automation does inside DM Champ itself — no app to connect, nothing to set up first. They’re grouped in the picker the same way they’re grouped here.
Fields that point at something already in your account are dropdowns: a pipeline and its stages, a contact list, a tag, a team member, a task stage, an event type, a draft broadcast or a WhatsApp template. Pick it from the list. When the value should come from an earlier step instead (a stage name sent in by a webhook, say), click Use a value from an earlier step instead under the field and insert it with the + button.
Contacts
| Action | What it does |
|---|---|
| Create contact | Adds a new contact. Channel decides where the contact is reached, and so where a later Send message step delivers: leave it on the account default for WhatsApp, pick SMS to text them from your connected SMS number (a form lead who asked for texts, for example), or pick Email to reach them by email — then the email address is what identifies the contact, the phone number is optional, and the account needs the Email channel connected. For the phone-based channels a phone number is required. If a contact with that number (or, on Email, that address) already exists on that channel, the step returns the existing contact instead of failing or creating a duplicate, keeps that contact’s channel, and the run log notes that it did so. Later steps get the contact ID either way. Custom fields shows one box per custom field on your account (you create them on the Contacts page under Manage fields); fill any of them from earlier steps, an order number from a webhook for example. Empty boxes are skipped. When the contact already exists, the values you filled are saved onto that contact. This is how you follow up by email with someone who wrote to you on another channel — see Example: email follow-ups for website chat leads |
| Update contact | Changes a contact’s name, email, phone number or custom fields. Only the custom fields you fill in are changed; the contact’s other custom fields stay as they are |
| Find contact | Looks a contact up by phone number or email, so later steps can use their details. The same person can exist once per channel (a website-chat contact and an email contact sharing one address, for example), so an email lookup can be narrowed to one channel. When nobody matches, the step stops the automation; switch on Keep going when no contact matches and it carries on instead, with found set to false, so a Condition on ${nodes.find_contact.found} can create the contact or skip ahead |
| Find contacts | Lists contacts — everyone, a free-text search, one list, or filtered. The quick way: With tag returns only contacts carrying a tag, Without tag leaves out everyone carrying one (tags matched by name; a name that doesn’t exist fails the step with a clear message, so a typo can’t quietly return nobody). The powerful way: Advanced filters opens the same rule builder smart lists use, so you can filter on anything a smart list can — tags, lists, channel, status, activity dates, AI on/off, do-not-disturb, name/email/phone, deal stage, custom fields — with a live count of how many contacts match. When Advanced filters are set they take over and the simple fields above are ignored. How many sets how many contacts the step returns, up to 1,000 per run (it defaults to 50); anything over 100 is fetched in batches behind the scenes, so a daily sweep over a few hundred contacts fits in one run |
| Turn AI on or off for a contact | Switches the AI agent on or off for that one contact, without touching anyone else |
| Set do-not-disturb | Stops (or resumes) anything outbound going to that contact, with an optional note saying why |
| Set custom field | Writes one custom field on a contact and leaves the others alone. Pick the field from the list of your custom fields, or choose Type a field key instead for a new one or a key coming from an earlier step — a field that doesn’t exist yet is created on the contact |
| Add contact to list / Remove contact from list | Moves a contact on or off one of your contact lists |
| Assign AI agent | Hands the contact to a different AI agent, so that agent’s persona and settings take over from the next message — the same thing as Assign AI Agent in a chat’s menu, but done by the workflow. Pick the agent from the list; the field also accepts a live classic campaign for older setups. Optionally let the new agent reply straight away. This is how you switch agents mid-conversation: keyword entry points only decide who answers a brand-new conversation, so an Incoming message trigger narrowed to a word like “support” followed by this action moves an existing chat to your support agent. Step-by-step: Switch AI Agent Mid-Conversation |
| Set contact tag / Remove contact tag | Applies or removes a tag by name. A tag that doesn’t exist yet is created |
| Send conversion to Meta | Reports one conversion (a deal won, a booked consult) to your Meta dataset, so your Meta ads optimise on real results and not only on messages. Needs Meta connected under Settings → Ad click tracking; without it the step fails with “Meta is not connected”. Pick the Event name (Purchase, Schedule, Lead or your own), optionally a Value and Currency, and who it is about: a Contact, or just an Email or Phone, so a buyer from another app works too. It sends every time it runs, so use Event ID to stop Meta counting the same conversion twice. See Send conversions from automations |
| Assign contact to a team member | Hands the contact to one of your team members, so it shows as theirs in the inbox. Leave the team member empty to unassign it again |
Messaging
| Action | What it does |
|---|---|
| Send message | Sends a message on the channel the contact is already on — WhatsApp, SMS, Instagram or Messenger, whichever they came in on. For a contact your automation created itself (a form lead, say), that is the Channel chosen in the Create contact step, so pick SMS there when the message should go out as a text. You can attach an image or file by link, and with a media link the text can be left empty. For anything that is not an image, fill in Media type with the file’s MIME type (application/pdf, audio/ogg, video/mp4) so the channel attaches it the right way, and optionally File name for the name the recipient sees on a document. To deliver audio as a WhatsApp voice note (the play bubble, not a file), turn on Send as voice note and make the audio OGG/Opus with media type audio/ogg. An MP3 sent as a voice note plays on some phones and shows as a file on others, so convert first. This one action replaces the old separate “Send WhatsApp” and “Send SMS” steps, which both did exactly this anyway; automations that still use them keep working |
| Send WhatsApp template | Sends one of your approved WhatsApp templates, which is what reaches someone outside WhatsApp’s 24-hour window. Give it either a contact or a plain phone number — with a number, the contact is looked up and created if there isn’t one yet. Once you pick the Template, Template variables shows one box per variable in it ({{1}}, {{2}}, or named ones like {{first_name}}); insert a value from an earlier step with the + button, such as the customer’s name or order number from a webhook. A variable you leave empty is filled from the contact’s own details. For a template that lives in your own WhatsApp Business Account (it carries the Meta label on the Templates page), you also get a row for the template’s text header variable (Header variable) and one for each dynamic website button (Website button 1 (URL suffix), the part added to the end of the button’s link). Map each one in the step. If the template’s variables were changed in Meta, open the step again after the next sync and re-map them. The step waits up to 20 seconds for WhatsApp’s answer. If WhatsApp refuses the template (for example a variable left empty or a template that is not approved), the step fails and the run shows WhatsApp’s reason. If no answer comes in time, the step passes with a note that delivery is not confirmed yet; the final status is in the contact’s chat. See Example: WhatsApp order confirmation from Shopify. Needs the WhatsApp Business API channel connected. See WhatsApp Templates |
| Launch broadcast | Starts a broadcast you already built and saved as a draft — the same as pressing Launch on it. The broadcast needs an audience, an opener and a connected sender; if anything is missing the step fails and says which |
| Send WhatsApp Web message | Sends through a QR-linked WhatsApp Web phone, addressed by number in full international format (+31612345678). For accounts on the WhatsApp Web channel. The number you address it to is only a recipient — it does not need to be connected as a channel itself (a manager’s phone receiving booking reports is the typical case). If you do connect the recipient’s phone as a second channel in the same account, every message between the two phones is logged twice (once per channel) and the new number may be the one picked to send, which on its first warm-up day has a new-contact cap of 0 — the run then fails with Daily limit of 0 new contacts reached. Keep the recipient as a plain number. Sends are also refused when the recipient contact is on Do Not Disturb (the run shows Contact is on Do Not Disturb list); turn DND off on that chat first |
Tasks
| Action | What it does |
|---|---|
| Create task | Creates a task, optionally with a description, a due date, an assignee and a contact |
| Update task | Changes a task’s title, description, stage, priority, due date or contact |
| Find task / Find tasks | Loads one task, or a list narrowed by stage, priority, contact, deal, assignee or due date — so the automation can branch on what it finds |
Deals
| Action | What it does |
|---|---|
| Create deal | Creates a deal on the board you choose. Pick the Pipeline first, and the Stage list then shows only that pipeline’s stages (change the pipeline and the stage is cleared, so you pick again). The stage is required. With a pipeline picked, a stage that comes from an earlier step can be the stage’s name as well as its ID; one that isn’t in that pipeline stops the step with a message instead of putting the deal on the wrong board |
| Update deal | Changes a deal’s title, value, stage, status or contact |
| Move deal stage | Moves a deal to another stage and puts the card at the top of that column |
| Find deal / Find deals | Loads one deal by id, or a list of deals newest first — optionally only the ones in one pipeline, in one stage or belonging to one contact — so the automation can branch on a stage or a value |
Appointments
| Action | What it does |
|---|---|
| Create appointment | Books an appointment for a contact on one of your bookable event types. It can also record a booking that was made somewhere else — your own CRM, a class schedule, another booking tool: leave the event type empty and give a Title instead, and the booking appears on the Appointments page with no availability check and no calendar sync. See Bookings made outside the platform |
| Cancel appointment | Cancels an appointment, with an optional reason. It stays on record as cancelled rather than disappearing |
| Reschedule appointment | Moves an appointment to a new time. Set the end time as well as the start — it isn’t worked out again from the event type’s length |
| Find appointment / Find appointments | Loads one appointment, or a list for one contact, one day or one status |
| Find available slots | Lists the free slots on one of your event types between two moments, so a later step can offer or book one |
Other
| Action | What it does |
|---|---|
| Log event | Records a custom event in your account’s automation event log — handy for counting how often something happened |
| Check credit balance | Reads the account’s credit balance at that moment so a Condition after it can branch on it — for example ${nodes.<step>.balance} < 100 to warn yourself before the credits run out. It only reads; it never spends or tops up |
| Alert human | Emails and notifies you that someone needs to step in, at low, medium or high priority, naming the contact if you point it at one |
| Send email to my team | Emails you or your team a message you write, for example “New deal” with the contact’s name, phone number and a link. Only goes to your own addresses: your login email, a team member’s email, or a notification email you verified under Settings → Notifications (leave To empty to use your login email). Anyone else is refused; to email a contact or lead, use the Email (your mail server) step. Write the Subject and the Message body in plain text: line breaks are kept and links become clickable. Fill in a Contact ID to add a button that opens that contact’s chat. It sends the email only, with no app or phone alert, and up to 200 of these emails go out per account in 24 hours. Use Alert human instead when someone has to step in |
Agency
| Action | What it does |
|---|---|
| Update sub-account | Changes one of your client accounts from inside the run: its spending limit, its monthly allowance, whether an unused allowance rolls over to next month, and its block level (active, soft blocked or hard blocked). It already points at the account from the trigger, so on a Sub-account created or Sub-account activity automation there’s nothing to fill in but the values you want changed — anything you leave empty stays as it is. See Automate what happens to client accounts |
Account API actions
Underneath the actions above, the step picker has a section called Account API, collapsed until you open it. It holds one action for every endpoint of the DM Champ API, around 390 of them, grouped by the part of the account they belong to: Contacts, Deals, Pipelines, Tags, Tasks, Appointments, Broadcasts, Knowledge base, FAQs, Summaries, Messages, Sub-accounts and the rest. Anything the API can do, an automation can now do as a normal step, with no HTTP request step, no API key and no code.

Open Account API in the palette and the endpoints are sorted into areas. Each card names the action and the call behind it, like Deals · POST /v1/deals.

One generated action's settings. Every parameter the endpoint takes gets its own field, and the ones that expect a list or an object are boxes you type JSON into.
A few things to know about them:
- Each action’s settings show one field per parameter the endpoint takes. A field that expects an object or a list of items is a box you type JSON into. Every field accepts values from earlier steps in the usual
${…}form, inserted with the + button. - The step on the canvas shows the method and address it calls, for example
PUT /v1/pipelines/:pipelineId, so you can look the endpoint up in the API reference when you want the detail on what it returns. A part of the address starting with a colon is a value you fill in on the step, so that one really calls/v1/pipelines/defaultonce Pipeline ID is set todefault. - Actions that delete something carry a red warning in their settings. They do exactly what the API call does, straight away, and there is nothing to undo afterwards.
- The actions at the top of the picker, the ones listed in the tables above, are unchanged. They stay the quickest way to do the common things, and most automations never need to open this section at all.
On an agency account, the actions that can act on a client account have a Sub-account field. Actions that cannot are left without one on purpose: filling a sub-account in on an endpoint that ignores it would have run the step on your own agency account without telling you, so the field only appears where it genuinely works.
Example: set up a new client account’s pipeline and tags. This is the zero-code version of what used to need a script.
- Trigger: Sub-account created.
- Account API → Tags → Create or assign a tag (
POST /v1/tags), with the tag’s name and Sub-account set to${trigger.sub_account.id}. - Account API → Pipelines → Update a pipeline (
PUT /v1/pipelines/default), with your stages in the JSON field. A stage’strigger_tagis written asusers/<the sub-account id>/tags/<the tag id the previous step returned>, both inserted with the + button.
Every client account you create from then on gets the same board and the same tag rules, without you opening it.
Example: email yourself a summary when someone books.
- Trigger: Appointment booked.
- Account API → Summaries → Summarise a conversation (
POST /v1/summaries), pointed at the contact from the trigger. - Email, with the summary from step 2 in the body.
How variables are written. Anything you insert with the + button lands as ${…} — for example ${trigger.contact.first_name} or ${trigger.appointment.start_time} — and that is the only format the automation resolves. The {{first_name}} style you may know from broadcast templates is not understood here: it is sent exactly as typed, so the message arrives with {{first_name}} in it instead of the name. If a message came through with the placeholder text still in it, that is almost always why — delete the placeholder and insert it again with the + button. Custom fields sit under contact like everything else about the person (${trigger.contact.your_field_key}). A field name with spaces, a question mark or other symbols (a Facebook lead form sends each question as its own field) goes in brackets and quotes, like ${trigger["what_service_are_you_interested_in?"]}; the + button inserts it that way for you. ${…} can also hold a small bit of code that changes the value, such as ${ trigger.contact.phone.replace("+", "") }: see Expressions. Under every field that holds a variable, a Result box shows the text as it would come out with your sample data: a green variable resolved (its value is shown), an amber one cannot be checked yet because its step has not been tested or the trigger has no captured event, and a red one points at a field that is not in the sample, which is usually a typo or the wrong path. For a bit of code inside ${ } the box shows what it works out to with the sample, or in red why it fails. Variables also work inside a field that holds a list or a group of values (such as a list of records to link, or a set of properties): each ${…} in it is filled in, and one that is the whole value keeps its type, so a number stays a number and a list stays a list.
Sample data without a test run. A step you would rather not run while building (one that creates a contact or sends a message) can get its sample by hand: open the step, click Pin sample under Output sample, paste or type what the step returns, and click Pin sample again. The variable picker, the Result box and the tests of later steps then use it, and it is marked Pinned until a real Test step replaces it. Live runs never use a pinned sample, only what the step really returns. On a Webhook trigger, Save as sample keeps the payload you typed as the trigger’s sample without running anything, while Send test event also starts a test run. The Sample payload (for testing) box must hold valid JSON, the same shape the outside tool will send: keys and text values in straight double quotes, and a double quote inside a text value written as \" (for example { "note": "she said \"hi\"" }). While the text is not valid JSON the box shows Invalid JSON and neither button saves or sends anything.
One thing worth knowing about filling these in: anything ending in ID — Contact ID, Task ID, Appointment ID — is meant to be inserted from an earlier step with the + button rather than typed by hand; the hint under each field says so.
Most actions also have a Sub-account ID field at the bottom of their settings: leave it empty and the step runs on your own account, or point it at one of your sub-accounts and the step acts inside that account instead.
Example: appointment reminders 24 hours and 3 hours before
This is the automation most people build first, so here it is end to end.
1. Start the automation. AI Studio → Automations → New automation, then click the trigger on the canvas.
2. Choose the trigger. Click Change trigger, open Appointments, and pick Before an appointment.
3. Pick your reminder times. Under Reminders, click the 24 hours before and 3 hours before chips. Need something that isn’t offered — 45 minutes, say? Type the number of minutes in Something else and click Add. You can have up to five reminders in one automation, and at least one: with none set, the automation never runs.
If any of your appointments start early enough that a reminder would land overnight, switch on Respect quiet hours in Automation settings (the gear icon at the top right) — the reminder still runs on time, the message just waits until 8 AM in the contact’s local time. See Respecting quiet hours.
Each reminder runs once per appointment, so two reminders means two runs for the same booking. It covers every appointment DM Champ knows about: bookings on the built-in calendar and the tables your AI books through Zenchef, Formitable, OpenTable or Trafft. A reservation made directly in the restaurant’s own system (its widget, the phone, a walk-in) never reaches DM Champ, so it gets no reminder. It applies to appointments already in your calendar, not only ones booked after you switch it on — and it keeps up with changes: move an appointment and its reminders move with it, cancel it and they’re cancelled too. A reminder whose moment has already passed when the booking is made (a 24-hour reminder on an appointment booked this afternoon) is simply skipped rather than sent late.
4. Optional: give each reminder different wording. Add a Condition step after the trigger and pick Reminder: minutes before as the field, ==, and 1440 as the value. The true path is the day-before message (“See you tomorrow at…”), the false path the three-hour one (“See you shortly at…”). Skip this if the same wording is fine for both.
5. Send the message. Add a Send message action. For Contact ID, click + and insert the appointment’s contact. For the message, write your reminder and use + to drop in the contact’s first name and the appointment’s start time — for example:
Hi ${trigger.contact.first_name}, a reminder about your appointment on ${trigger.appointment.start_time}. Reply CONFIRM to keep it or CANCEL if you can't make it.
Other details the trigger hands you: the appointment’s room, its summary, the contact’s phone and email, and which reminder this run is. The start time arrives as a full date and time (2026-09-01T10:00:00Z), so if you’d rather the message said “tomorrow at 10:00”, put an AI step in front of the message and ask it to phrase the time in the contact’s own words.
6. Test, then turn it on. Click Run to fire it once with sample data, check the run in Log, then flip the Enabled switch.
About WhatsApp’s 24-hour window. If the contact last messaged you more than 24 hours ago, WhatsApp won’t let a normal message through — which is exactly the situation a day-before reminder is in. Use the Send WhatsApp template action for that reminder instead, with an approved template; a template is allowed to open the conversation, and it also reopens the 24-hour window so the contact’s reply can be handled normally. The three-hour reminder can often use a plain Send message, because by then the contact may have replied to the first one. See WhatsApp Templates for creating and getting one approved.
About Confirm / Cancel buttons. Tappable quick-reply buttons aren’t available from automations yet. The way to do it today is to ask for a word back — “reply CONFIRM to keep it or CANCEL to cancel” — and handle the answer either with your AI agent (it reads the reply like any other message and can cancel or rebook) or with a second automation on the Incoming message trigger, narrowed to messages containing CANCEL, which looks the booking up with Find appointments for that contact, runs Cancel appointment, and tells you with Alert human.
Example: ask for a review 2 hours after an appointment
There is no “after an appointment” trigger: Before an appointment only fires ahead of the start. To message a contact once the appointment is over, start on the booking and wait until after it ends.
- Trigger: Appointment booked.
- A Delay step with Wait type set to Until a specific moment. Insert the appointment’s end time with the + button (
${trigger.appointment.end_time}) and set Offset to120for two hours after it ends. - A Send message (or Send WhatsApp template if the contact may not have written to you in the last 24 hours, see the 24-hour window note above) with your review link.
This works for every appointment DM Champ knows about: the built-in calendar and the bookings your AI makes through Zenchef, Formitable, OpenTable or Trafft. A booking made directly in the other system (its own booking page, its admin, the phone) never reaches DM Champ, so it starts nothing. Turn the automation on with the Enabled switch, or nothing runs.
Example: turn a missed WhatsApp call into a chat
A restaurant in the middle of service, a garage with someone under a car, a clinic between patients: the phone rings, nobody can pick up, and the caller tries the next place on the list. This automation messages every missed caller on WhatsApp within seconds and lets your AI agent take it from there.
Just want the text back? You don’t need to build this by hand: on Settings → Channels, each WhatsApp Web number has a Text back missed calls switch that creates this exact automation for you, with your message, and the SMS via Twilio card has the same switch for a Twilio number you connected yourself. See WhatsApp Web → Text back missed calls and SMS → Text back missed calls. Build it yourself, as below, when you want conditions, a different agent for missed callers, or follow-up steps.
It works for calls to a number connected through WhatsApp Web and for calls to the Twilio number you connected for SMS. A missed call is any call you didn’t pick up: the caller hung up after a few rings, or it rang out. Calls you answer and calls you decline don’t count, and group calls are ignored.
1. Create the automation. AI Studio → Automations → New automation, click Change trigger, open Messaging and pick Missed call. Leave Number on Any number and it fires for every missed call on every number in the account, WhatsApp Web and SMS alike; the field lists your WhatsApp Web numbers and your SMS number, so pick one there to run this automation for calls to that number only (a second automation can cover another number with its own text).
2. Send the message. Add a Send message action. For Contact ID, click + and insert the caller from the trigger. Then write the text, for example:
Sorry we missed your call, we’re in the middle of service right now. Are you looking to book a table? I can help you right here.
The caller becomes a contact the moment the call is missed (with the name from their WhatsApp profile, if they show one), so the message lands in their chat like any other, and a caller who already has a chat with you gets it in that chat. The reply goes out from the number they called. WhatsApp Web has no 24-hour window, so a plain message is allowed even though they never wrote to you.
If you would rather send from a specific line, both Send message and Send WhatsApp Web message have a Send from field listing your WhatsApp Web numbers. On Automatic the message goes out from the number the person last talked to, which for a missed call is the number they rang.
If the caller rang your SMS number, the same Send message step with the caller’s Contact ID answers them — the text goes out as an SMS from your one connected SMS number, so there is nothing to pick under Send from. The caller is saved as an SMS contact when the call ends, their chat shows a Missed voice call line, and their reply is handled by the SMS number’s AI Agent. The text is sent through your own Twilio account, so your Twilio SMS rates apply. If one automation covers both kinds of number, ${trigger.channel} tells you which you are dealing with — whatsapp_web or sms — so a Condition on it can give a WhatsApp caller different wording from a texted one.
3. Let your agent take over. When the caller answers, the conversation is handled like any new chat on that number: the agent set as that number’s default under Who answers new conversations replies. Only if a different agent should handle missed callers add an Assign AI agent action before the message.
Useful values for a Condition or in the message text: ${trigger.contact.first_name}, ${trigger.contact.phone_number}, ${trigger.channel} (whatsapp_web or sms), ${trigger.call.to_number} (the number they called; for one automation per number use the trigger’s Number field instead of a condition), ${trigger.call.is_video}, ${trigger.call.missed_at} and ${trigger.is_new_contact}, which is true for someone who has never chatted with you, so you can greet a stranger differently from a regular.
Calls to a WhatsApp Business API number don’t fire this trigger, and neither do calls to numbers bought through the platform or to a phone used as an Android SMS gateway. Callers are only saved as contacts on accounts that have a Missed call automation switched on; without one, a missed call leaves no trace in the app. For the SMS number there is one more condition: the Text back missed calls switch on the SMS via Twilio card has to be on, because that switch is what points the number’s calls at DM Champ in your Twilio account. An automation built by hand for the SMS number does nothing while that switch is off; turn it on first, then customise the automation it created.
Example: ignore anyone you tag as spam
Tag a time-waster once and never hear from them again — the same shape works for “only reply to people tagged VIP”, “skip anyone tagged Customer”, and so on.
1. Start the automation. AI Studio → Automations → New automation, then click the trigger on the canvas.
2. Choose the trigger. Click Change trigger, open Messaging, and pick Incoming message. Leave the channel on Any channel so it covers every conversation.
3. Add the check. Add a Condition step after the trigger. In the first field, click the + button, type tag in the search box, and pick tag_names (the one under contact, in the incoming message trigger group) — that’s the contact’s tags by name. The field fills itself in as ${trigger.contact.tag_names}. Set the comparison to contains, and in the value box type the tag exactly as you named it, for example spam.
4. Decide what happens. On the true path — the one that runs when the contact does have the tag — add a Set do-not-disturb action, which stops anything outbound going to them. Fill in three things: Contact ID with the + button (insert the contact from the trigger, don’t type it), Do not disturb as true, and optionally a Reason for your own records. Prefer to keep the conversation open but silence the AI? Use Turn AI on or off for a contact instead, with AI enabled set to false. Leave the false path empty: everyone else carries on as normal.
5. Test, then turn it on. Click Run to fire it once with sample data, check the run in Log, then flip the Enabled switch.
Three things worth knowing:
- Capital letters count. A tag named Spam won’t match
spam. Copy the name from Settings → Tags if you’re unsure — see Creating Tags. - Pick tag_names, not tags. Right next to it in the same list is tags, which holds internal ID codes rather than names. A check against that one can never match a word you type, so the automation would quietly take the false path forever. If you’d rather type the field than pick it, the one you want is
${trigger.contact.tag_names}. - It applies from their next message. The check reads the tags the contact has at the moment the message arrives, so tagging someone doesn’t undo messages already sent. If you want the tag itself to be the starting point instead, use the Contact updated trigger, which fires the moment a tag is added or removed.
Example: join a list with a keyword (and leave it with another)
Let people subscribe to a list by sending a word — JOIN, VIP, OFFERS — and unsubscribe just as easily. Two small automations, one contact list, and your broadcasts get a self-building audience.
1. Start the automation. AI Studio → Automations → New automation, then click the trigger on the canvas.
2. Choose the trigger. Click Change trigger, open Messaging, and pick Incoming message. Pick the channel the keyword should work on — WhatsApp, say — or leave it on Any channel. In Contains text, type the keyword, for example JOIN. Capital letters don’t matter here: join, Join and JOIN all match.
3. Add them to the list. Add an Add contact to list action. Insert Contact ID with the + button — the contact comes with the trigger — and pick the list people should land on. If you don’t have one yet, create it first (see List and Contact Management).
4. Optional: confirm it. Add a Send message action after it, Contact ID inserted the same way, with something like “You’re on the list! Reply STOP any time to leave.”
5. Test, then turn it on. Click Run to fire it once with sample data, check the run in Log, then flip the Enabled switch.
6. Build the way out. Make a second automation the same way: same trigger with STOP in Contains text, and a Remove contact from list action instead. Mention the stop word in what you send — people who know a polite exit exists don’t block the number to get one.
From then on, any broadcast can use that list as its audience — everyone who sent the keyword, minus everyone who later sent the stop word. An ongoing broadcast that messages new list members picks keyword joiners up automatically.
One thing worth knowing: Contains text matches anywhere in the message, so “joining you tomorrow” contains join. Pick a word people wouldn’t use mid-sentence, or use the trigger’s Regex field when you need an exact match.
Example: move an Instagram or Facebook lead to WhatsApp when the window closes
A common ad funnel: people see your Instagram or Facebook ad, DM your page, and your AI agent qualifies them and asks for their phone number. When a lead types their number or email in the chat, the AI saves it to the contact’s phone and email fields automatically, in real time — there’s nothing to map or configure for that part.
What doesn’t happen automatically is the hop to WhatsApp. Instagram and Messenger only allow messages within 24 hours of the contact’s last message, don’t support templates to reopen the conversation, and DM Champ's built-in follow-ups always stay on the channel the conversation is on — so once the window closes, follow-ups on those channels are simply skipped (see Follow-Up System). This automation makes the hop for you, using the number the AI captured:
1. Start the automation. AI Studio → Automations → New automation, then click the trigger on the canvas.
2. Choose the trigger. Click Change trigger, open Contacts, and pick Contact updated, narrowed to the phone number field. It fires the moment the AI saves a captured number — no matter which channel the conversation is on.
3. Add a Delay. A fixed wait of, say, 24 hours gives the conversation — and any quick follow-ups inside the window — time to do their job first. If the lead converts in the meantime, you can stop the run with a Condition before the next step (checking the contact’s tag_names for something like Customer, the same pattern as in Example: ignore anyone you tag as spam).
4. Send the template. Add a Send WhatsApp template action, insert Contact ID with the + button, and pick one of your approved templates. Templates are allowed to open a conversation, so this works no matter how long the lead has been quiet — that’s the whole point of the step. Variables you leave empty in Template variables fill from the contact’s own fields, and it needs your WhatsApp Business API channel connected. See WhatsApp Templates for creating and approving one.
5. Test, then turn it on. Click Run to fire it once with sample data, check the run in Log, then flip the Enabled switch.
When the lead replies, the conversation is on WhatsApp — inside its 24-hour window — and your agent carries on from there.
Example: WhatsApp order confirmation from Shopify
Send a WhatsApp template the moment someone orders in your Shopify store, with their name and order number filled in. It needs an approved template (for example “Hi {{1}}, thanks for your order {{2}}!”) and your WhatsApp Business API channel connected.
1. Start with a Webhook trigger. Create a new automation, pick the Webhook trigger and copy its web address. Add ?secret= and the secret from the trigger step to the end of the address, because Shopify cannot send a custom header.
2. Point Shopify at it. In Shopify go to Settings > Notifications > Webhooks, create a webhook for Order creation in JSON format, and paste the address. On the trigger step, click Start listening under Listen for incoming webhooks, place a test order (or send a test notification from Shopify), and pick the captured order as the sample, so its fields show up in the + picker.
3. Optional: save the order number on the contact. Add a Create contact step. Set Phone number to ${trigger.phone}, First name to ${trigger.customer.first_name}, and under Custom fields fill your order number field (for example order_id) with ${trigger.name}. If the customer is already a contact, the order number is saved onto the existing contact.
4. Send the template. Add a Send WhatsApp template step. Type the template’s name exactly as it appears under WhatsApp templates, then fill in who it goes to: insert the Contact ID from the Create contact step, or put ${trigger.phone} in Phone number. Under Template variables, fill the boxes:
{{1}}(the customer’s name):${trigger.customer.first_name}{{2}}(the order number):${trigger.name}, which is Shopify’s order name, such as#1001
Use the order’s own phone number, ${trigger.phone}, in international format. The customer’s phone field, ${trigger.customer.phone}, is often empty on Shopify orders, and a send with no number fails.
5. Test it. Click Run with the captured sample, open the run in Log, and check the message went out with the name and order number in it.
Then switch the automation on. While it is off, Shopify’s webhooks are still received and show up under Listen for incoming webhooks, but no messages are sent.
Abandoned checkout reminders: Shopify has no abandoned cart webhook. Use the same setup with Shopify’s Checkout update webhook, add a Delay, then a Condition on a tag that a second automation (on Order creation) gives to buyers, so the reminder only goes to people who did not order.
Example: email follow-ups for website chat leads
Someone chats with your agent on the website, leaves their name and email, and disappears before booking. You want to check in by email over the next few days — and stop the moment they say they booked. Two automations do it; both use your connected Email channel, so the replies land in Chats and your email agent handles them.
Before you start. Turn on Collect visitor info on the chat widget so every visitor leaves a name and email. Connect the Email channel and give its agent a tag rule on the Tags tab such as Booked — apply when the person says they have booked or scheduled their session (AI Agents → Tags). That tag is the off switch.
Automation 1 — move the lead onto email.
- Trigger Incoming message, narrowed to the Website chat channel, and in Automation settings switch Allow re-entry off so each visitor goes through it once, on their first message. (Not New contact: a “contact created” trigger followed by a Create contact step is the self-triggering shape the editor refuses — see Automations that trigger themselves.)
- A Condition on the contact’s email — does not contain
unknown@— so visitors who left no address end here instead of failing the next step. - A Delay of, say, an hour, so the website conversation finishes first.
- Create contact with Channel set to Email. Insert the visitor’s email with the + button (
${trigger.contact.email}), and their first and last name the same way. Leave the phone number empty. If that address is already an email contact, the step simply returns it. - Send message with the Contact ID inserted from the Create contact step. This goes out as an email from your connected inbox — the first check-in, for example “Were you able to book your session?”. A proactive email has no earlier message to reply to, so its subject is Message from followed by your inbox’s sender name; replies keep that subject.
Automation 2 — the follow-up sequence, on the email contact.
- Trigger New contact, narrowed to the Email channel. It fires the moment Automation 1 creates the email contact (and for anyone who emails you first — add a Condition on a tag or the contact’s details if you only want website leads in it).
- Delay two days.
- Find contact by the contact’s email (insert it from the trigger), narrowed to the Email channel, so the check reads the contact’s tags as they are now rather than as they were when the run started.
- Condition: the found contact’s tag_names contains
Booked. Leave the true path empty — that ends the run for anyone who booked. - On the false path, Send message to the contact with your second check-in, then Delay, Find contact, Condition and Send message again for as many rounds as you want. Finish with a Set contact tag such as
Sequence completeso you can see who went all the way through.
When the lead replies to any of the emails, the conversation is already in Chats on the email contact, the email agent answers, and if the reply says they booked, the agent’s tag rule adds Booked and the next round’s Condition ends the sequence. Leave Stop on response off in Automation 2: it would end the sequence on any reply, including “not yet”.
Two things worth knowing. The website chat and the email conversation are two contacts that share an address, not one merged thread — the widget chat stays on the website contact and the emails live on the email contact. And a contact is one per channel, so if the same person emails you first, Automation 1’s Create contact step returns that existing email contact instead of making a second one.
Example: AI at night, your team by day
Some teams run the shifts inverted: the AI agent covers the evening and night, and real people take over in the morning. Set the agent’s active hours to the night shift and that’s half the job — a message that arrives during the day is answered by the AI when its hours open again, and it shows under the Outside hours filter in Chats in the meantime.
The other half is making the morning hand-over automatic, so a chat the AI opened at 9 PM doesn’t sit waiting until 9 PM the next day when the customer writes back at 10 AM. Two small automations do it — the first pauses the AI on any chat that gets a daytime message, the second gives everything back to the AI in the evening:
Automation 1 — hand daytime chats to your team.
- AI Studio → Automations → New automation. The trigger is already Incoming message; leave it account-wide or narrow it to one agent.
- In Automation settings (the gear icon at the top right), switch on Only run during these hours and set your team’s day — say 08:00 to 20:45 — with your timezone (see Only running during certain hours).
- Add a Turn AI on or off for a contact action: insert Contact ID with the + button, set AI enabled to
false. - Add a Set contact tag action with a tag like
day-shift, so the evening automation can find these chats again.
Now any message that lands during the day pauses the AI on that conversation on the spot: the chat appears under your AI paused filter and your team replies from there. Replying by hand also cancels the AI’s queued answer for that chat, so the AI won’t jump back in when its hours open.
Automation 2 — give the chats back to the AI in the evening.
- New automation with the On schedule trigger, set to a few minutes before the AI’s hours start — for a 9 PM start, the cron
50 20 * * *with the same timezone. - Add a Find contacts action filtered to With tag
day-shift. - Add a Loop over the result with two steps inside: Turn AI on or off for a contact with AI enabled
true, then Remove contact tagday-shift.
Chats your team finished during the day go back to the AI for the night, and a daytime chat nobody got to still gets its queued AI answer the moment the agent’s hours open — nothing falls through.
From the toolbar on the canvas, Run fires the automation once using sample data, without turning it on for real contacts — a safe way to check it works. Replay re-runs it with the real data from your last run. Log opens the run history, so you can see every past run and whether it succeeded, failed, or is still in progress.
Cancelling a run. A run that is still going, including one waiting on a Delay or held for quiet hours, can be stopped by hand: click Cancel on its row in the run history, or open the run and click Cancel run, then confirm. The run stops where it is and shows as Cancelled. Steps it hadn’t reached yet never run, so nothing more is sent from it; steps that already ran are not undone. Only that one run is affected: the automation stays on for everyone else.
Three things help you catch a mistake before your contacts do:
- A step that’s missing something required won’t start. Fields marked required are checked before a run, and before the Enabled switch will flip: if a Send message step has no Contact ID, you get a message naming the step and the field instead of a run that quietly fails. Fill it in and the switch works as normal. Pausing is never blocked.
- Variables that don’t resolve are reported. If a
${…}value in one of your steps found nothing — a misspelled field name, or data the trigger doesn’t actually carry — the step still runs with that part blank, and the run detail shows a Warnings line naming exactly which ones came through empty. That’s usually the answer to “why did my message arrive with a hole in it”. - A run that took the other branch says so. After a run, the run panel on the canvas lists every Condition it passed with the branch it took (Yes or No), and counts the steps that did not run. A run whose condition answered No still finishes as succeeded, so this is where you see that the steps on the Yes path were skipped.
- A refused step shows as failed, with the reason. A step the app turned down (a duplicate contact, a stage that doesn’t exist, a template that isn’t approved) is marked failed and shows what it said, instead of a green tick with nothing behind it.
For automations that start with a Webhook trigger, the run history also warns you about calls that never became runs: if something has been calling your webhook with a missing or wrong secret, a banner at the top counts those rejected requests and reminds you what to fix — the caller needs to send the secret from the trigger step, either as an X-Webhook-Secret header or as ?secret= at the end of the URL. Before, those calls were simply turned away with nothing to show for it, which made a misconfigured caller look like the automation never fired at all.
Example: a birthday message every morning
Send each contact a message on their birthday. You need a Date custom field holding the birthday (the year can be anything, only the month and day are used).
- AI Studio → Automations → New automation with the On schedule trigger, set to
0 9 * * *(every day at 9 AM) with your timezone. - Add a Find contacts action. Under Advanced filters, add the rule Birthday, anniversary is in the next N days,
0(today only). Set How many to1000: it defaults to 50, and only the contacts it looks at can match. - Add a Loop and, with the + button, pick the contacts list from the Find contacts step as the list to go through.
- On the loop’s body handle, add a Send message step. For Contact ID, insert the loop item’s ID with the + button (it reads
${nodes.loop_1.item.id}when the loop is calledloop_1). The message can greet them by name the same way, with the item’sfirst_name.
That’s the whole automation: no Condition or Transform step is needed, because Find contacts already returns only today’s birthdays. On a day without one the loop runs zero times and the run still shows as succeeded.
The birthday rule counts days in UTC. For a morning run that is fine almost everywhere; if you are more than 9 hours ahead of UTC, run it later in the day (after 11 AM in Sydney, after 1 PM in New Zealand) so your date and the UTC date are the same.
Turning an Automation on
Use the Enabled switch to turn it live (it saves your draft first) — from that point on, it fires for real every time its trigger happens. Flip it back to Paused any time to stop it without losing your work. Pausing stops new runs from starting; runs that are already waiting on a Delay or on quiet hours still finish. To stop one of those, click Log and use Cancel on its row in the run history. An automation has to be paused before you can delete it.
Automations that trigger themselves
Some flows can set off their own trigger. The classic case: an automation that starts on Task created and has a Create task step. The new task fires the trigger again, which creates another task, and so on, one run every second or so, each one costing credits. The same thing can happen with Contact created plus Create contact, Appointment booked plus Create appointment, or Deal created plus Create deal.
Three safeguards catch this:
- The editor tells you straight away. As soon as a flow has that shape, a red banner appears above the canvas naming the step and the fix, the step gets a red marker, and the Enabled switch, Run and Replay stay off until it is fixed. You can keep editing and saving a paused automation; if the automation is already on, the change won’t save until you pause it or fix the step. Flows that might re-trigger themselves (a Contact updated trigger with a step that changes the contact — editing details, tags, lists or custom fields, assigning it to a team member, switching its AI on or off, setting do-not-disturb or handing it to another AI agent, for example) get an amber warning instead, which doesn’t block anything: pick a field for the trigger to watch so it only starts on the changes you care about. A Deal stage changed trigger with a Move deal stage step, and a Tag applied or Tag removed trigger with a Set contact tag or Remove contact tag step, get the same amber warning: those are ordinary flows (“when it reaches Won, tag them”) right up until the step writes back the very thing the trigger watches, so we say so and leave the choice to you.
- The AI builder refuses the obvious shape. If you describe a flow where a “something was created” trigger is followed by a step that creates that same kind of thing, the builder won’t produce it and tells you which step to change. When you want to change the very thing that started the run (set a due date on the task that was just created, tag the contact that just came in), use the matching Update step on the trigger’s ID instead: Update task with
${trigger.task.id}, Update contact with${trigger.contact.id}. Updating doesn’t re-fire a “created” trigger. - A runaway automation switches itself off. An automation that keeps running at more than 30 runs a minute for several minutes in a row is paused automatically, and a failed run appears in its history explaining why. One with the self-feeding shape above is stopped much sooner, after 10 runs in a minute. Normal bursts are fine: importing 300 contacts into a Contact created automation fires 300 runs in one minute and then goes quiet, which is not a loop. Test runs you start yourself from the toolbar are never counted. Fix the flow, then turn it back on.
What automations cost
Each run of an automation uses 0.25 credits, whatever started it — a trigger firing for real, or you pressing Run or Replay yourself. The 0.25 is charged once, when the run starts, so a run that a Condition step stops at the first branch still counts as a run and still costs the same 0.25. You can build automations with as many steps as you like at no extra cost; the only step that adds to the price is the AI step, which uses a further 0.25 credits each time it runs. The AI step always runs on the Max model, whichever model your Agents use, so switching an Agent to Mini does not change what an automation costs. If your balance runs out, a run fails with a clear “not enough credits” message in the run history, and new runs go through again as soon as you top up.
On the Champions Circle Insider Rate, both charges are 20% lower: 0.20 credits when a run starts and 0.20 for each AI step.
A step from the Account API section is billed exactly as the same call to the API would be. Most endpoints cost nothing at all, and the ones that run AI for you, conversation summaries for example, cost what the API charges for them. There is no extra per-step charge on top of that.
The run charge always comes out of the account the automation is saved in. Pointing a step at one of your sub-accounts through its Sub-account ID field doesn’t move the bill — the run is still charged to your workspace, while anything the step sets in motion inside the sub-account (an AI reply to an unpaused chat, for example) is billed to that sub-account as normal. If you want a client’s own balance to pay for the runs themselves, build the automation inside their account instead.
Using your own Anthropic key (BYOK)? Automations are billed in credits regardless. The AI step runs on our built-in automation AI, not on your key, so it always uses 0.25 credits per run just like the flat 0.25 credits per automation run. Your key keeps covering your Agents’ replies as before; the two don’t interact.
Automations vs. Entry Points
These sound similar but solve different problems:
- An Entry Point only ever does one thing — match an event and hand the conversation to an Agent. No delays, no conditions, no branching.
- An Automation is the full workflow tool — multiple steps, conditions, delays, and actions across contacts, deals, tasks, and outside integrations, not just conversation handoff.
If all you need is “route this conversation to that Agent,” use an Entry Point. If you need a sequence of steps or logic beyond that, build an Automation.
Copy an automation to a client account
If you run client accounts, an automation you have perfected on your own account can be stamped into any of them. In the automations list, click the Copy to client account button (the two arrows) on the automation’s row, tick the client accounts to copy it into, and click Copy to. The button sits next to Duplicate and only appears on an agency account.

Tick the client accounts and click Copy to. The window reminds you the copy arrives paused, with lists, calendars, connected apps and saved keys left for the client to fill in.
The copy keeps the automation’s name, its trigger and every step. Two things are deliberately different in the client’s account:
- It arrives paused. Nothing runs until someone opens it in the client’s account, checks it over and flips Enabled on.
- Anything that pointed at your account is cleared, because those IDs mean nothing in someone else’s account: the client account a step was aimed at, a chosen smart list, a chosen calendar event and a chosen database connection. Fill them in with the client’s own once the copy is there — the steps themselves are untouched.
If a step or the trigger pointed at one of your AI agents, the copy tries to point at the client’s matching agent by itself. That works when the client’s agent came from the same snapshot or was copied over from the same agent of yours — we know the two are the same setup, so the link is re-made automatically. When there is no match, the copy tells you which agent it could not place; open the automation in the client’s account, pick the agent there, and switch it on.
Working with several automations at once
Every row in the automations list has a checkbox, and the header checkbox selects everything currently shown. With automations selected, a bar at the bottom of the screen offers Enable, Pause and Delete — each asks you to confirm first, and deleting also removes the automations’ run history. Press Escape to clear a selection.
Next Steps
- Entry Points — the simpler routing tool for handing conversations to an Agent.
- AI Agents — the persona an Automation or Entry Point can route to.
- Broadcasts — send a one-off or ongoing message to a list of contacts.
- Booking System — set up the appointments an automation can remind people about, book, move or cancel.
- WhatsApp Templates — needed to message someone outside WhatsApp’s 24-hour window.