# Automatic actions for messages Autoresponder and automatic message actions in Ritevo: triggers, time conditions, template and AI replies, loop protection. A message action reacts to what happens in your inbox: a new thread, a new message, a status change. Most often it replies to the customer - with fixed text, a template filled with the thread's data or a reply written by AI - assigns the thread to a specific user, sets your own custom status, marks the thread as read or favorite, adds a note and much more. The general rules are covered in [How automatic actions work](https://ritevo.com/en/docs/automations/how-it-works). > **Required integration:** You need an integration with [message fetching](https://ritevo.com/en/docs/messages/fetching-messages) turned on. The **Send AI message to thread** step also needs an AI integration (OpenAI or Claude), and **Send template message to thread** needs a saved message template. > **Good to know:** Add the **Message received from customer** condition to every action that replies to a customer. Without it the action also reacts to its own replies and can loop - explained below. ## Where to find actions Message actions are in the **Messages → Actions** menu (in the left panel). For every action the list shows its trigger, conditions and steps, and whether it is active. You add a new action with the **Add new action** button in the top right corner. The breadcrumbs at the top of the page (**Dashboard → Messages → Actions**) always show where you are. ![The list of automatic message actions with the Actions item highlighted in the left panel; the Add new action button in the top right corner is framed](https://ritevo.com/docs/automations/en-message-actions-list.webp) The action form looks the same as for orders: basic settings at the top (name, description, trigger, time zone, **Active**), conditions on the left, steps on the right. ![An empty new-action form for messages: basic settings, a condition card and a step card](https://ritevo.com/docs/automations/en-message-action-form-empty.webp) ## Triggers - **New thread** (API: "New thread" = `NEW_THREAD`) - a thread that was not in Ritevo before appeared. Usually this is the customer's first message about a matter. - **Reply in thread** (API: "Reply in thread" = `MESSAGE_RESPONSE`) - a new message appeared in an existing thread. **No matter who wrote it** - the customer or you. - **Template reply in thread** (API: "Template reply in thread" = `TEMPLATE_MESSAGE_RESPONSE`) - an automatic action sent a template reply. - **AI reply in thread** (API: "AI reply in thread" = `AI_MESSAGE_RESPONSE`) - an automatic action sent an AI reply. - **Status changed** (API: "Status changed" = `USER_DEFINED_STATUS_CHANGED`) - your own custom thread status changed. - **Assigned user changed**, **Read status changed**, **Favorite status changed**, **Own note changed**. (API: "Assigned user changed" = `ASSIGNED_USER_CHANGED`, "Read status changed" = `READ_STATUS_CHANGED`, "Favorite status changed" = `FAVORITE_STATUS_CHANGED`, "Own note changed" = `OWN_NOTE_CHANGED`) The customer's first message fires **New thread**, and every later one in the same conversation fires **Reply in thread**. A thread can be old: a customer who bought from you a year ago often writes in the same conversation, and then it is **Reply in thread**, not **New thread**. So always build an autoresponder as a **pair of actions** - one with the **New thread** trigger and one with the **Reply in thread** trigger, with the same conditions and steps. ## Why the "from customer" condition is necessary Messages you send - by hand or through an action - come back to Ritevo on the next fetch from the channel and are also "a new message in the thread". The **Reply in thread** trigger does not tell direction. Only conditions do: - **Message received from customer** (API: "Message received from customer" = `MESSAGE_FROM_INTERLOCUTOR`; value in `booleanValues`: always `[true]`) - the last message in the thread is from the customer. - **Message sent to customer** (API: "Message sent to customer" = `MESSAGE_FROM_SELF`; value in `booleanValues`: always `[true]`) - the last message is from you. An action without the **Message received from customer** condition **can loop**. Its own reply comes back on the next message fetch as a new message in the thread, the action replies to it again - and so on at every fetch, without end. The safety switch described on the general page will not stop this, because several minutes pass between the replies and it reacts to many runs in a short time. The customer would keep getting the same reply until you turn the action off. This one condition solves the problem at the source, so always add it. ## Conditions ### Who wrote and where from - **Message received from customer** / **Message sent to customer**. (API: "Message received from customer" = `MESSAGE_FROM_INTERLOCUTOR`, "Message sent to customer" = `MESSAGE_FROM_SELF`; value in `booleanValues`: always `[true]`) - **Integration is** / **Integration is not** (API: "Integration is" = `INTEGRATION_IS`, "Integration is not" = `INTEGRATION_IS_NOT`; value in `uuidValues`: ids of integrations with messages: `GET /integrations/marketplaces`, `GET /integrations/shops`, `GET /integrations/email`, `GET /integrations/messaging`) - which channel the thread comes from. You pick from the list of your integrations - one or several. With several, any of them is enough. - **Conversation type is** / **Conversation type is not** (API: "Conversation type is" = `THREAD_TYPE_IS`, "Conversation type is not" = `THREAD_TYPE_IS_NOT`; value in `enumValues`: `MESSAGE`, `DISCUSSION`, `CLAIM`) - Message, Dispute or Claim; one or several. - **Conversation status is** / **Conversation status is not** (API: "Conversation status is" = `THREAD_STATUS_IS`, "Conversation status is not" = `THREAD_STATUS_IS_NOT`; value in `enumValues`: `DISPUTE_ONGOING`, `DISPUTE_CLOSED`, `DISPUTE_UNRESOLVED`, `CLAIM_SUBMITTED`, `CLAIM_ACCEPTED`, `CLAIM_REJECTED`) - the state of the dispute or claim in the sales channel. ### Content - **Message contains keywords** / **Message does not contain keywords** (API: "Message contains keywords" = `MESSAGE_CONTAINS_KEYWORDS`, "Message does not contain keywords" = `MESSAGE_NOT_CONTAINS_KEYWORDS`; value in `stringValues`: a list of words or text fragments; any of them is enough, letter case does not matter) - the **last** message in the thread is checked. One of the given words is enough, letter case does not matter. - **Topic contains keywords** / **Topic does not contain keywords**, **Own note contains keywords** / **Own note does not contain keywords** (API: "Topic contains keywords" = `TOPIC_CONTAINS_KEYWORDS`, "Topic does not contain keywords" = `TOPIC_NOT_CONTAINS_KEYWORDS`, "Own note contains keywords" = `OWN_NOTE_CONTAINS_KEYWORDS`, "Own note does not contain keywords" = `OWN_NOTE_NOT_CONTAINS_KEYWORDS`; value in `stringValues`: a list of words or text fragments; any of them is enough, letter case does not matter) - work the same way. ### Time of day, day and date - **Action run time from** / **to** (API: "Action run time from" = `CURRENT_TIME_FROM`, "to" = `CURRENT_TIME_TO`; value in `offsetDateTimeValue`: a date-time with the offset of the action's zone; only the hour and minute count, for example `2026-01-10T16:00:00+00:00`) - what time it is at the moment the action runs. - **Message time from** / **to** (API: "Message time from" = `MESSAGE_TIME_FROM`, "to" = `MESSAGE_TIME_TO`; value in `offsetDateTimeValue`: a date-time with the offset of the action's zone; only the hour and minute count, for example `2026-01-10T16:00:00+00:00`) - what time the last message came in. - **Action run day is** / **is not**, **Message day is** / **is not** (API: "Action run day is" = `CURRENT_DAY_OF_WEEK_IS`, "is not" = `CURRENT_DAY_OF_WEEK_IS_NOT`, "Message day is" = `MESSAGE_DAY_OF_WEEK_IS`, "is not" = `MESSAGE_DAY_OF_WEEK_IS_NOT`; value in `integerValues`: numbers 1-7, where 1 is Monday and 7 is Sunday) - days of the week. - **Action run date from** / **to**, **Message date from** / **to** (API: "Action run date from" = `CURRENT_DATE_FROM`, "to" = `CURRENT_DATE_TO`, "Message date from" = `MESSAGE_DATE_FROM`, "to" = `MESSAGE_DATE_TO`; value in `offsetDateTimeValue`: a date-time with an offset; the whole instant counts) - for a holiday period, for example. > **Good to know:** Times are counted in the time zone set in the action. A range is two conditions (**from** and **to**), and the boundaries are included. A range across midnight needs two actions - [why](https://ritevo.com/en/docs/automations/how-it-works#conditions). ### Thread state - **Status is** / **Status is not** (API: "Status is" = `USER_DEFINED_STATUS_IS`, "Status is not" = `USER_DEFINED_STATUS_IS_NOT`; value in `uuidValues`: ids of custom thread statuses: `GET /messages/statuses`) - your own custom statuses, one or several. - **Assigned user is** / **is not** (API: "Assigned user is" = `ASSIGNED_USER_IS`, "is not" = `ASSIGNED_USER_IS_NOT`; value in `uuidValues`: ids of company users: `GET /company/users`) - one or several users. - **Conversation is read** / **Conversation is not read**, **Conversation is a favorite** / **Conversation is not a favorite**. (API: "Conversation is read" = `READ_STATUS_IS`, "Conversation is not read" = `READ_STATUS_IS_NOT`, "Conversation is a favorite" = `FAVORITE_STATUS_IS`, "Conversation is not a favorite" = `FAVORITE_STATUS_IS_NOT`; value in `booleanValues`: a list with one value: `[true]` or `[false]`) - **No note** / **Has note** / **Note was removed**. (API: "No note" = `OWN_NOTE_IS_EMPTY`, "Has note" = `OWN_NOTE_IS_NOT_EMPTY`, "Note was removed" = `OWN_NOTE_CHANGED_TO_EMPTY`; value in `booleanValues`: always `[true]`) - **Read status changed from** / **to**, **Favorite status changed from** / **to** (API: "Read status changed from" = `READ_STATUS_CHANGED_FROM`, "to" = `READ_STATUS_CHANGED_TO`, "Favorite status changed from" = `FAVORITE_STATUS_CHANGED_FROM`, "to" = `FAVORITE_STATUS_CHANGED_TO`; value in `booleanValues`: a list with one value: `[true]` or `[false]`) - they react to the change itself. ## Steps - what an action can do ### Replying to the customer - **Send message to thread** (API: "Send message to thread" = `SEND_MESSAGE_TO_THREAD`; value in `stringValue`: text up to 2000 characters) - fixed text, up to 2000 characters. Sent literally, without inserted values. - **Send template message to thread** (API: "Send template message to thread" = `TEMPLATE_SEND_MESSAGE_TO_THREAD`; value in `uuidValue`: id of a message template: `GET /messages/templates`) - content from a saved template. Inserted values work only in a template: **Other party**, **Thread topic**, **Thread status**, **Order number**, **Order ID (external)**, **Offer ID (external)**. In the template editor you click the value you want, and when the message is sent the thread's data is filled in. If the thread does not have a given value (for example a topic or an offer ID), it is inserted as empty. - **Send AI message to thread** (API: "Send AI message to thread" = `AI_SEND_MESSAGE_TO_THREAD`; value in `uuidValue`: id of an AI integration: `GET /integrations/ai`) - the chosen AI integration writes the reply and Ritevo **sends it to the customer right away**. ### How the AI reply works - AI receives **the text of the customer's last message** and the instructions you entered in the AI integration settings. It does not receive the earlier thread history or order data. - Everything AI should know about your business - working hours, return policy, tone of voice - goes into the AI integration's instructions. - There is no draft mode. The reply goes to the customer without your approval, so start with narrow conditions, for example keywords or a single channel. - If AI returns an error, nothing is sent and you will see the error in the messages audit. The cost of replies is billed by your account with the AI provider. ### Tidying the thread - **Assign user** (API: "Assign user" = `UPDATE_ASSIGNED_USER`; value in `uuidValue`: a user id from `GET /company/users`; `null` removes the assignment) - also removing the assignment. - **Update status** (custom), **Update read status**, **Update favorite status**, **Update own note**. (API: "Update status" = `UPDATE_USER_DEFINED_STATUS`; value in `uuidValue`: ids of custom thread statuses: `GET /messages/statuses` | "Update read status" = `UPDATE_READ_STATUS`, "Update favorite status" = `UPDATE_FAVORITE_STATUS`; value in `booleanValue`: `true` or `false` | "Update own note" = `UPDATE_OWN_NOTE`; value in `stringValue`: text up to 255 characters; `null` clears the note) ## Example: an out-of-hours autoresponder You work Monday to Friday, 8:00-16:00. A customer who writes outside those hours should be told when you will reply. > **Good to know:** You create every action below **twice**: once with the **New thread** trigger and once with the **Reply in thread** trigger. The conditions and the step are the same in both. Without the second version the autoresponder skips customers who write in a conversation that already exists in Ritevo - even if the previous message was a year ago. ### Action 1 - weekend - Conditions: **Message received from customer**, **Action run day is** Saturday, Sunday. - Step: **Send template message to thread** with text like "Thank you for your message. We will reply on the next working day." ### Action 2 - working days after 16:00 - Conditions: **Message received from customer**, **Action run day is not** Saturday, Sunday, **Action run time from** 16:00. - Step: the same as in action 1. ### Action 3 - working days before 8:00 - Conditions: **Message received from customer**, **Action run day is not** Saturday, Sunday, **Action run time to** 08:00. - Step: the same as in action 1. In total you create six actions: action 1, 2 and 3, each in two versions - with the **New thread** trigger and with the **Reply in thread** trigger. Actions 2 and 3 are separate because the 16:00-08:00 range crosses midnight. The day-of-week condition in actions 2 and 3 makes sure the customer does not get two replies at the weekend. ## Example: an AI reply with an assigned employee A pair of actions from the app: AI replies to every customer message and the thread goes to a chosen employee. Both actions have the same conditions and steps and differ only in the trigger. ### Action 1 - the New thread trigger - Trigger: **New thread**. - Condition: **Message received from customer**. - Steps: **Send AI message to thread** with the chosen AI integration, then **Assign user** to the chosen person. ![The action form: the New thread trigger, the Message received from customer condition, the Send AI message to thread and Assign user steps](https://ritevo.com/docs/automations/en-message-action-new-thread.webp) ### Action 2 - the Reply in thread trigger - The same, only with the **Reply in thread** trigger - so AI also replies to the customer's later messages in the same conversation. ![The same action with the Reply in thread trigger](https://ritevo.com/docs/automations/en-message-action-reply.webp) > **Good to know:** The **Message received from customer** condition is essential here: without it action 2 would reply to AI's own replies. An AI reply goes to the customer right away, so start with a single channel (the **Integration is** condition) and check the results in the audit. ## In which channels the reply works The action sends the reply the same way you reply by hand. If a channel does not allow a manual reply, the action will not reply there either. On a given integration's page you can check whether it lets you reply to messages, disputes and claims. ## What a message action will not do - It will not send an attachment. - It will not insert values from the thread into plain text - only into a template. - It will not close a dispute or claim or change their state in the sales channel. - It will not reply with a delay or "if nobody answered within an hour". - There is no "once per thread" limit and no pause between replies - you set the scope with the trigger and conditions. ## Run audit Runs are in **Settings → Audit → Messages**. What the results mean is explained in [How automatic actions work](https://ritevo.com/en/docs/automations/how-it-works#history). ## Example of saving through the API Action 2 from the autoresponder example (working days after 16:00) in the version with the **New thread** trigger. You create the second version the same way, changing `triggerType` to `MESSAGE_RESPONSE`. The general rules of saving are on the [How automatic actions work](https://ritevo.com/en/docs/automations/how-it-works) page. ```json { "name": "Autoresponder - working days after 16:00 (new thread)", "description": "Tells the customer when we will reply", "active": true, "userTimezone": "Europe/Warsaw", "triggerType": "NEW_THREAD", "conditions": [ { "type": "MESSAGE_FROM_INTERLOCUTOR", "booleanValues": [ true ] }, { "type": "CURRENT_DAY_OF_WEEK_IS_NOT", "integerValues": [ 6, 7 ] }, { "type": "CURRENT_TIME_FROM", "offsetDateTimeValue": "2026-01-10T16:00:00+01:00" } ], "actionSteps": [ { "stepOrder": 1, "action": { "type": "TEMPLATE_SEND_MESSAGE_TO_THREAD", "uuidValue": "" } } ] } ``` --- All help in one file: https://ritevo.com/llms-full.txt. Help map with links to every page: https://ritevo.com/llms.txt.