> ## Documentation Index
> Fetch the complete documentation index at: https://docs.messagedesk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Relay Recipes

> A practical reference library of common MessageDesk Relay configurations: after-hours auto-reply, anonymous-contact capture, keyword routing, phone-line routing, webhooks to external systems, and more.

# Relay Recipes

A practical reference library of common Relay configurations. Each recipe lists the **trigger**, any **conditions**, the **actions**, and a brief **why this works** note.

<Note>
  **Every recipe here is a starting point.** Adjust the wording, labels, assignees, active hours, and conditions to match your team's workflow. For step-by-step instructions on building a Relay from scratch, including how to use **AND/OR** between conditions, chain actions, and add delays, see [Create and edit a Relay](/relays/create-edit).
</Note>

***

## Customer service

### 1. After-hours auto-reply

| Field         | Value                                                                                                         |
| ------------- | ------------------------------------------------------------------------------------------------------------- |
| **Trigger**   | Message Received                                                                                              |
| **Condition** | Active hours: set your business hours, then toggle **Trigger outside of business hours** to invert the window |
| **Actions**   | **Reply to message:** "We'll get back to you at 8am. Reply STOP to opt out."                                  |

**Why this works:** Inverting the Active hours window means the Relay only fires when an inbound message lands **outside** your business hours, so customers always get an immediate acknowledgement. The STOP language keeps you compliant with carrier opt-out requirements.

<Note>
  **Auto-replies don't mark a conversation as Read.** When this Relay sends its after-hours reply, the conversation moves to **Replied** status and leaves the Unread filter. It isn't marked Read until a teammate opens it in the Inbox. See [Relays and conversation status](/relays/create-edit#relays-and-conversation-status) for details.
</Note>

<Tip>
  Add a **Delay** to the Reply action to avoid sending repeat auto-replies inside a tight back-and-forth.
</Tip>

***

### 2. First-touch reply for anonymous contacts

| Field          | Value                                                                                                                                               |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Trigger**    | Message Received                                                                                                                                    |
| **Conditions** | Is anonymous conversation = **true**                                                                                                                |
| **Actions**    | **Reply to message:** "Thanks for texting us! What's your first and last name so we know who to help?" → **Add labels to the conversation:** `Lead` |

**Why this works:** New inbound texts from unsaved numbers come in as **anonymous conversations**. A first-touch reply captures the contact's name while it's fresh, and the `Lead` label gives sales/intake a single filter to work from. See [Anonymous, opted out & blocked](/contacts/anonymous-opt-out-blocked) for how anonymous status is determined.

***

### 3. Opted-out conversation handler

| Field         | Value                                                                                                                                                                                                                        |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Trigger**   | Message Received                                                                                                                                                                                                             |
| **Condition** | Contact is **opted out** *(use the closest available condition; today this is most commonly handled by a keyword condition like **Message contains text "STOP"** or by routing on a label applied earlier in your workflow)* |
| **Actions**   | **Add labels to the conversation:** `Opted Out` → **Assign teammates to the conversation:** support queue                                                                                                                    |

**Why this works:** Opt-outs need human review. Labeling the thread keeps it visible to compliance and support, and routing it to your support queue ensures someone confirms the customer's request was honored. Once `Opted Out` is applied, downstream filters and Relays can avoid texting that contact again.

<Note>
  MessageDesk automatically blocks sending to **opted-out contacts** at the workspace level. This Relay is for **internal awareness and audit**, not for blocking the outbound message itself.
</Note>

***

## Operations and routing

### 4. Phone line routing

| Field         | Value                                                                                                                                                         |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Trigger**   | Message Received                                                                                                                                              |
| **Condition** | **My phone number equals** = the specific connected phone line                                                                                                |
| **Actions**   | **Assign teammates to the conversation:** designated teammate(s) → **Add labels to the conversation:** line-specific label (e.g., `Front Desk`, `Sales Line`) |

**Why this works:** Teams running multiple phone lines (Front Desk, Support, Sales) want every inbound message on that line to land with the right owner immediately. Adding a line-specific label also gives you ready-made filtered views in the Inbox.

***

### 5. Keyword-based routing

| Field         | Value                                                                                                                                 |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| **Trigger**   | Message Received                                                                                                                      |
| **Condition** | **Message contains text** = `HELP` (or `SUPPORT`, `BILLING`, etc.)                                                                    |
| **Actions**   | **Reply to message:** "Got it. A support teammate will be with you shortly." → **Assign teammates to the conversation:** support team |

**Why this works:** Keyword routing is fast triage: the customer gets an instant acknowledgement and the right team picks up the thread without manual sorting. Combine with **My phone number equals** if you want the keyword to behave differently on different lines.

<Tip>
  Stack multiple keyword Relays (one per keyword) and use a default Relay without a keyword condition as a catch-all.
</Tip>

***

### 6. Auto-assign (round-robin note)

| Field          | Value                                                                                       |
| -------------- | ------------------------------------------------------------------------------------------- |
| **Trigger**    | Message Received                                                                            |
| **Conditions** | Optional: **My phone number equals** a specific line, or message lacks an existing assignee |
| **Actions**    | **Assign teammates to the conversation:** teammate                                          |

**Why this works:** A single Relay assigns every inbound conversation to one teammate. **True round-robin distribution requires multiple Relays**, one per teammate, each segmented by a different **line** or **label** condition so they don't all fire on the same message. There isn't a built-in "rotate to next teammate" action today. This multi-Relay pattern is the supported workaround.

<Tip>
  Pair this with a `Triage` label and an Inbox filter on **Assignee = Unassigned** so anything that slips through is easy to spot.
</Tip>

***

## Webhooks and integrations

<Note>
  Webhook actions require a configured webhook endpoint and signing secret. Set those up in [**Settings → Developer Tools**](/settings/workspace-settings/developer-tools) before turning on the Relays below. See [Send Webhook](/relays/webhooks) for the full payload format, headers, and signature validation.
</Note>

### 7. Push new inbound message to an external system

| Field          | Value                                       |
| -------------- | ------------------------------------------- |
| **Trigger**    | Message Received                            |
| **Conditions** | None (or scope by line/keyword)             |
| **Actions**    | **Send Webhook** → your configured endpoint |

**Why this works:** Streams every new inbound text to your CRM, data warehouse, ticketing tool, or notification service. Pair with **My phone number equals** to limit the firehose to a specific line, or add **Message contains text** to forward only certain keywords.

***

### 8. Notify an external system on conversation close

| Field          | Value                                         |
| -------------- | --------------------------------------------- |
| **Trigger**    | Message Received *(see workaround below)*     |
| **Conditions** | A label like `Closed` is applied (workaround) |
| **Actions**    | **Send Webhook** → your configured endpoint   |

**Why this works:** Today the only supported Relay trigger is **Message Received**. There isn't a dedicated `ConversationClosed` trigger. The supported workaround is to use a **closing label** as the signal: when an agent closes a conversation, they also apply a label like `Closed`, and a Relay scoped to that label forwards the close event downstream.

<Note>
  **Workaround setup:**

  1. Create a workspace label like `Closed`.
  2. Train your team to apply the label when they close a conversation (or wire it into an existing close-out workflow).
  3. Build a Relay: **Trigger** Message Received, **Condition** a label `Closed` is on the conversation, **Action** Send Webhook.

  When MessageDesk adds a native `ConversationClosed` trigger, swap the trigger and remove the label condition.
</Note>

***

## See also

* [Create and edit a Relay](/relays/create-edit): step-by-step Relay building, including AND/OR conditions, delays, and active hours
* [Send Webhook](/relays/webhooks): payload structure, signature validation, and retry behavior
* [Developer Tools](/settings/workspace-settings/developer-tools): configure your webhook endpoint and signing secret
* [Relays overview](/relays/overview): concepts and examples
