---
title: "Message actions"
space: "Raven"
url: "https://docs.frappe.io/raven/frappe-apps/message-actions"
updated: "2026-10-19"
---

A message action turns a message into something in a Frappe app. For example, it can create a document from a message, with the message text already filled in. An admin sets up the actions. Everyone can then use them on any message.

## Use an action on a message

1. Point to a message and click **⋯**.
2. Point to **Actions**.
3. Click the action.
4. Check the values in the dialog. Some are filled in from the message.
5. Click **Submit**.

<picture>
  <source srcset="/files/raven-dark-apps-action-menu.webp" media="(prefers-color-scheme: dark)">
  <img src="/files/raven-light-apps-action-menu.webp" alt="The Actions submenu on a message" width="404">
</picture>

<picture>
  <source srcset="/files/raven-dark-apps-action-run.webp" media="(prefers-color-scheme: dark)">
  <img src="/files/raven-light-apps-action-run.webp" alt="The dialog of a message action" width="560">
</picture>

Raven shows a message when the action is done. If the action created a document, click **View** in that message to open the document. The message also gets the document card, if it did not have one already.

**Actions** only shows on the menu when your site has at least one enabled action.

An action runs with the permissions of the person who uses it. If they can't create the document, the action fails and Raven shows the error. The dialog stays open, so they can fix a value and try again.

## Set up an action

:::note
Only Raven admins and System Managers can create and change message actions.
:::

1. Open **Settings** and click **Message Actions**.
2. Click **Create**.
3. Fill in the **General** tab.
4. Click the **Fields** tab and add the fields the dialog should show.
5. Click **Create**.

### General

<picture>
  <source srcset="/files/raven-dark-apps-action-general.webp" media="(prefers-color-scheme: dark)">
  <img src="/files/raven-light-apps-action-general.webp" alt="The General tab of a message action">
</picture>

| Field | What it does |
| :--- | :--- |
| Name | The name of the action on the **Actions** menu. |
| Action Type | What the action does: **Create Document**, **Custom Function (API)** or **Server Script**. Each type is explained below. |
| Title | The title of the dialog. When you leave the **Name** box, Raven copies the name here. You can change it after that. |
| Description | Shown under the title of the dialog. |
| Success Message | Shown when the action is done. If it is empty, Raven shows **Action completed**. |

### Fields

Each row is a field in the dialog that people see when they use the action. The field's name is the key its value is sent under.

<picture>
  <source srcset="/files/raven-dark-apps-action-fields.webp" media="(prefers-color-scheme: dark)">
  <img src="/files/raven-light-apps-action-fields.webp" alt="The Fields tab of a message action">
</picture>

- Click **Add Field** to add one field.
- For **Create Document**, click **Import fields from** and the document type to add all its mandatory fields at once.
- Click the pencil on a row to change it, or the bin to remove it.

<picture>
  <source srcset="/files/raven-dark-apps-action-field-dialog.webp" media="(prefers-color-scheme: dark)">
  <img src="/files/raven-light-apps-action-field-dialog.webp" alt="The dialog for one field" width="608">
</picture>

| Field | What it does |
| :--- | :--- |
| Field | For **Create Document**: the field of the new document to fill. Picking it fills in the label and type. |
| Field Name | For the other two types: the name the value is sent under. |
| Label | The label in the dialog. |
| Type | The kind of input: Data, Number, Select, Link, Checkbox, Date, Time, Datetime or Small Text. |
| Validation | For Data: checks that the value is an email, a phone number or a URL. |
| Required | People must fill it in before they can submit. |
| Options | For Select: the choices, one on each line. |
| Document Type | For Link: the type of document to pick from. |
| Default Value Type | Where the starting value comes from. See the table below. |
| Default Value | The starting value. |
| Description | Help text under the field. |

| Default Value Type | Default Value |
| :--- | :--- |
| Static | A fixed value. |
| Message Field | A value from the message. See the table below. |
| Jinja | A template that uses the message, such as `{{ message.content }}`. `message` has every field of the message, and `message.message_url`. |

| Message Field | The value |
| :--- | :--- |
| Text (with HTML) | The message text, with its formatting. |
| Content (plain text) | The message text, without formatting. |
| File | The link to the file in the message. |
| Owner | The user who sent the message. |
| Creation | When the message was sent. |
| Message Type | Text, Image, File or Poll. |
| Linked DocType | The type of the document attached to the message. |
| Linked Document | The ID of the document attached to the message. |
| Channel ID | The ID of the channel. |
| Workspace ID | The workspace of the channel. |
| Message URL | A link that opens the message in Raven. |

Number fields are sent as numbers. Checkbox fields are sent as `1` or `0`. Datetime fields are sent as text, such as `2026-10-19 14:30:00`.

## Create Document

Raven creates a new document of the type in **Document Type**, filled in with the values from the dialog.

- Each field in the **Fields** tab fills the document field of the same name.
- Values with no matching field on the action are dropped.
- The document must pass its own checks. Every mandatory field needs a value, so use **Import fields from** to add them.
- After the document is created, Raven attaches it to the message, unless the message already has a document.
- The success message has a **View** button that opens the new document.

## Custom Function (API)

Raven calls a Python function in an app on your site. Use this when the action needs more than one document, or logic of its own.

<picture>
  <source srcset="/files/raven-dark-apps-action-custom-function.webp" media="(prefers-color-scheme: dark)">
  <img src="/files/raven-light-apps-action-custom-function.webp" alt="A Custom Function action in Settings">
</picture>

In **Custom Function Path**, enter the dotted path to the function, with no spaces. For a function `create_task` in the file `my_app/raven_actions.py`, the path is `my_app.raven_actions.create_task`.

Raven calls the function with one keyword argument for each field of the action. Each argument has the field name. Nothing else is passed, not even the message. To use a value from the message, add a field with **Message Field** as its **Default Value Type**.

A field that is left empty can arrive as an empty string, or not arrive at all. Give every optional argument a default.

The function runs as the person who used the action. If it raises an error, Raven shows the error and the dialog stays open. If it returns a dictionary with a `link`, the success message has a **View** button that opens that link.

This example has three fields on the action:

| Field Name | Type | Default Value Type | Default Value |
| :--- | :--- | :--- | :--- |
| `description` | Small Text | Message Field | Content (plain text) |
| `assigned_to` | Link, to User | Static | (empty) |
| `message_url` | Data | Message Field | Message URL |

```python
# my_app/raven_actions.py
import frappe


def create_task(description, assigned_to=None, message_url=None):
	"""Called by a Raven message action. Each argument is a field of the action."""
	if not description:
		frappe.throw("Add a description first.")

	# ToDo is a document type that every Frappe site has.
	todo = frappe.get_doc(
		{
			"doctype": "ToDo",
			"description": f"{description}<br><br>From Raven: {message_url or ''}",
			"allocated_to": assigned_to or frappe.session.user,
		}
	).insert()

	# Raven shows a View button that opens this link.
	return {"link": todo.get_url()}
```

## Server Script

Raven runs a Server Script with the values from the dialog. Use this to add logic without writing an app.

<picture>
  <source srcset="/files/raven-dark-apps-action-server-script.webp" media="(prefers-color-scheme: dark)">
  <img src="/files/raven-light-apps-action-server-script.webp" alt="A Server Script action in Settings">
</picture>

### Before you start

Server scripts must be turned on for the whole bench. A system administrator runs this command on the server:

```bash
bench set-config -g server_script_enabled 1
```

It can take up to a minute to take effect.

### Write the script

1. Under the **Server Script** field, click **View Server Scripts**.
2. Create a Server Script with **Script Type** set to **API**.
3. Save it, and make sure it is not disabled.
4. Back in **Message Actions**, pick it in the **Server Script** field.

:::note
You need the Script Manager role to see and write server scripts.
:::

### What the script gets

The script reads its input from `frappe.form_dict`:

| Key | What it holds |
| :--- | :--- |
| `message_id` | The ID of the message the action was used on. |
| `action_id` | The ID of the message action. |
| `values` | The values from the dialog, as a dictionary keyed by field name. |

Read the values with `frappe.form_dict.get("values")`. `frappe.form_dict.values` does not work, because `values` is also a method of a Python dictionary. Read each value with `.get("field_name")`.

`frappe.session.user` is the person who used the action. The script runs with their permissions.

Raven does not use anything the script returns. It shows the **Success Message** when the script ends without an error. Call `frappe.throw("...")` to stop and show an error instead.

### Example: create a document and reply in the channel

This script creates a to-do from the message, then posts a reply in the channel as an agent. Add one field to the action: `details`, type Small Text, with **Message Field** and **Content (plain text)** as its default.

```python
# Script Type: API
message_id = frappe.form_dict.get("message_id")
values = frappe.form_dict.get("values") or {}

message = frappe.get_doc("Raven Message", message_id)

# ToDo is a document type that every Frappe site has.
todo = frappe.get_doc({
    "doctype": "ToDo",
    "description": values.get("details") or message.content,
}).insert()

# Agents are stored as Raven Bot records. Use the name of one of your agents.
agent = frappe.get_doc("Raven Bot", "Requests")
agent.send_message(
    channel_id=message.channel_id,
    text="Logged as " + todo.name + " by " + frappe.session.user + ".",
)
```

See [Agents](wiki:6e7bbec94d65) to create an agent.

## A full example

This example creates a document from a message, with the message text filled in. It uses **Create Document**, so no code is needed.

1. Open **Settings** and click **Message Actions**, then click **Create**.
2. In **Name**, enter a name, such as `Create a task`.
3. In **Action Type**, leave **Create Document**.
4. In **Document Type**, pick the type of document to create.
5. In **Description**, enter `Create a task from this message.`
6. In **Success Message**, enter `Task created.`
7. Click the **Fields** tab.
8. Click **Import fields from** and the document type. The mandatory fields are added.
9. Click the pencil on the field that should hold the message text.
10. In **Default Value Type**, pick **Message Field**. In **Default Value**, pick **Content (plain text)**.
11. Click **Save**, then click **Create**.

Now anyone can point to a message, click **⋯**, point to **Actions** and click **Create a task**. The dialog opens with the message text filled in.

## Change, turn off or delete an action

Click an action in the list to open it. Make your changes and click **Save**.

To hide an action without deleting it, click **⋮** at the top right and click **Disable**. Click **Enable** to turn it back on. To remove it for good, click **⋮** and then **Delete**.

## On the mobile app

Touch and hold a message, tap **Actions**, then tap the action.

<picture>
  <source srcset="/files/raven-dark-ios-message-actions.webp" media="(prefers-color-scheme: dark)">
  <img src="/files/raven-light-ios-message-actions.webp" alt="The actions for a message on the mobile app" width="300">
</picture>
