Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 83 additions & 25 deletions docs/automations/custom-automations.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ Project automations apply to work items within a single project.
2. In the **Custom automations** section, click **Create automation**.
3. Give your automation a descriptive name and an optional description, then save.
4. Click **Add trigger** and choose the event that should start the automation.
5. Optionally click **Add condition** to narrow when the automation runs. You can add multiple conditions the automation only fires when all conditions are met.
6. Click **Add action** to define what happens. Choose from **Add comment**, **Change property**, or **Run Script**. You can add multiple actions they execute in sequence.
5. Optionally click **Add condition** to narrow when the automation runs. You can add multiple conditions - the automation only fires when all conditions are met.
6. Click **Add action** to define what happens. Choose from **Add comment**, **Change property**, or **Run Script**. You can add multiple actions - they execute in sequence.
7. Click **Confirm**.
8. Click **Enable** when you're ready for it to go live.

Expand All @@ -44,7 +44,7 @@ Workspace automations can span your entire workspace or a specific set of projec

1. Go to **Workspace Settings → Automations**.
2. Click **Create automation**.
3. Choose which projects the automation should apply to all projects in the workspace, or a specific subset.
3. Choose which projects the automation should apply to - all projects in the workspace, or a specific subset.
4. Follow the same steps as a project automation: name → trigger → conditions → actions.
5. Enable when ready.

Expand Down Expand Up @@ -72,15 +72,16 @@ Conditions filter which work items an automation acts on. Without them, the auto
4. Choose an operator (is, in, contains, etc.) and set the value.
5. Add more conditions as needed.

Multiple conditions use **AND** logic by default all of them must match. You can also create **OR** groups where only one condition in the group needs to match.
Multiple conditions use **AND** logic by default - all of them must match. You can also create **OR** groups where only one condition in the group needs to match.

## Add actions

1. Open the automation and go to the **Action** tab.
2. Click **Add action** and choose a type:
- **Change property** — update a field on the work item
- **Add comment** — post a comment on the work item
- **Run script** — execute a saved script via the Runner
- **Change property** - update a field on the work item
- **Add comment** - post a comment on the work item
- **Run script** - execute a saved script via the Runner
- **Send webhook** - POST a payload to an external URL when the automation fires
3. Configure the action details (see [Actions](#actions) for parameters).
4. Add more actions if needed. They run in the order listed.

Expand All @@ -91,7 +92,7 @@ Multiple conditions use **AND** logic by default — all of them must match. You
- **Enable**: open the automation and click **Enable**. The automation must have at least one trigger and one action.
- **Disable**: open the automation and click **Disable** or toggle the status off.

You can't delete an enabled automation disable it first.
You can't delete an enabled automation - disable it first.

### Check automation run history

Expand Down Expand Up @@ -168,14 +169,71 @@ Updates a field on the work item.

Posts a comment on the work item. You write the comment text in a rich text editor. The comment is always internal and appears as coming from Automation Bot in the activity log.

You can include dynamic values in the comment using template variables for example, inserting the current priority or state name into the comment text.
You can include dynamic values in the comment using template variables - for example, inserting the current priority or state name into the comment text.

**Example:** Say you have an automation that triggers when a work item's state changes. You want to leave a note with context each time that happens. Your comment template might look like:

```
This item has been moved to a new state. Current priority: {{priority}}. Please check if the due date needs updating.
```
Comment on lines 176 to 178
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add a language identifier to the fenced code block.

Line 176 uses a plain triple-backtick block; specify the language (e.g., text) to satisfy markdown linting and keep docs lint-clean.

Proposed fix
-```
+```text
 This item has been moved to a new state. Current priority: {{priority}}. Please check if the due date needs updating.
</details>

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.22.1)</summary>

[warning] 176-176: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @docs/automations/custom-automations.md around lines 176 - 178, Update the
fenced code block that currently contains "This item has been moved to a new
state. Current priority: {{priority}}. Please check if the due date needs
updating." by adding a language identifier (e.g., text) after the opening triple
backticks so the block becomes text ... , ensuring markdown linting
passes; locate the block by searching for that exact string in
docs/automations/custom-automations.md and replace the opening withtext.


</details>

<!-- fingerprinting:phantom:triton:hawk -->

<!-- This is an auto-generated comment by CodeRabbit -->


#### Send webhook <Badge type="warning" text="Enterprise Grid" />

Posts an HTTP payload to a URL you specify whenever the automation fires. Use this to push automation events into external systems - trigger a deployment, open a ticket in another tool, post to a custom service, or sync data outside of Plane.

This is different from workspace webhooks, which fire on any matching event across your workspace. A Send webhook action fires only when this specific automation runs - you control the trigger, conditions, and timing.

**Configuration**

| Field | Required | Notes |
| -------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| URL | Yes | Must be a publicly reachable `http://` or `https://` address. Local and private network addresses are not accepted. |
| Secret key | Auto-generated | Generated when you save the action. Shown once in plain text - copy it before leaving. After that it appears masked as `plane_wh_••••XXXX`. |
| Custom headers | No | Up to 20 headers. Mark a header as secret to store its value encrypted - the value won't be returned in subsequent reads. |

**The secret key**

Plane generates a secret key when you first save the Send webhook action. It is shown in plain text once - copy and store it before navigating away. After that, it is masked and cannot be retrieved.

If your key is compromised or you lose it, open the action in the automation editor and click **Regenerate secret**. The old key stops working immediately. Update your server before regenerating or your signature verification will fail.

**What Plane sends**

Every request includes these headers:

| Header | Value |
| ------------------- | ---------------------------------------------- |
| `Content-Type` | `application/json` |
| `User-Agent` | `Autopilot` |
| `X-Plane-Delivery` | Unique ID for this delivery attempt |
| `X-Plane-Event` | The automation event that triggered the action |
| `X-Plane-Signature` | HMAC-SHA256 signature of the request body |

Custom headers you add are merged in. You cannot override the reserved headers listed above.

**Verifying the payload**

Use the `X-Plane-Signature` header to confirm the request came from Plane and wasn't tampered with. Compute an HMAC-SHA256 digest of the raw request body bytes using your secret key and compare it to the header value.

```python
import hashlib
import hmac

def verify_webhook(request_body_bytes: bytes, secret: str, signature_header: str) -> bool:
expected = hmac.new(
secret.encode("utf-8"),
request_body_bytes,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(expected, signature_header)
```

Use raw request body bytes - not a parsed or re-serialized version - or the signature will not match.

**Delivery behavior**

Plane makes a single attempt with a 30-second timeout. If the request fails or times out, it is not retried. Check your automation's Activity log to see whether the delivery succeeded and what response your server returned.

#### Run script <Badge type="warning" text="Enterprise Grid" />

Runs a saved script from your [Plane Runner](/automations/plane-runner) library. You pick the script from a dropdown. This is the only action available when using a scheduled trigger.
Expand All @@ -184,25 +242,25 @@ Runs a saved script from your [Plane Runner](/automations/plane-runner) library.

### How automations run

Every time something changes in Plane a work item is created, a state changes, a comment is posted Plane checks whether any of your enabled automations should respond. If a trigger matches, Plane evaluates any conditions you've set. If those pass, it runs the actions in order.
Every time something changes in Plane - a work item is created, a state changes, a comment is posted - Plane checks whether any of your enabled automations should respond. If a trigger matches, Plane evaluates any conditions you've set. If those pass, it runs the actions in order.

That's the whole flow: something happens → conditions are checked → actions run. If a condition doesn't match, nothing happens and the automation sits quietly. If an action runs into a problem, Plane stops there and marks that run as failed you can see exactly what happened in the Activity tab.
That's the whole flow: something happens → conditions are checked → actions run. If a condition doesn't match, nothing happens and the automation sits quietly. If an action runs into a problem, Plane stops there and marks that run as failed - you can see exactly what happened in the Activity tab.

Each event is only processed once per automation, so you won't end up with the same action firing twice on the same work item.

### Project automations vs. workspace automations

The distinction comes down to scope and reuse.

**Project automations** are the right choice when the rule is specific to one project. They're simpler to configure the states, labels, and members you pick from are all scoped to that project.
**Project automations** are the right choice when the rule is specific to one project. They're simpler to configure - the states, labels, and members you pick from are all scoped to that project.

**Workspace automations** are the right choice when you want the same behavior across multiple projects. Instead of recreating the same automation in five different places, you define it once and choose which projects it applies to all of them, or just a specific subset.
**Workspace automations** are the right choice when you want the same behavior across multiple projects. Instead of recreating the same automation in five different places, you define it once and choose which projects it applies to - all of them, or just a specific subset.

Either way, automations always act on individual work items. Workspace automations aren't doing anything different they're just defined once and applied more broadly.
Either way, automations always act on individual work items. Workspace automations aren't doing anything different - they're just defined once and applied more broadly.

### Automation bot

Every custom automation acts through its own dedicated bot account. When an automation changes a field or posts a comment, the activity log shows it came from "Automation Bot" not from any person on your team.
Every custom automation acts through its own dedicated bot account. When an automation changes a field or posts a comment, the activity log shows it came from "Automation Bot" - not from any person on your team.

There are two reasons this matters:

Expand All @@ -212,32 +270,32 @@ There are two reasons this matters:

### Why scheduled automations only run scripts

Most automations respond to something happening a trigger gives them a specific work item to act on. Scheduled automations are different. They fire at a time you set, not because of any particular event.
Most automations respond to something happening - a trigger gives them a specific work item to act on. Scheduled automations are different. They fire at a time you set, not because of any particular event.

Since there's no work item that kicked off the run, Plane has nothing to apply a property change or comment to. That's why the only available action for scheduled automations is Run script. The script defines the logic what to look for, which items to act on, and what to do with them.
Since there's no work item that kicked off the run, Plane has nothing to apply a property change or comment to. That's why the only available action for scheduled automations is Run script. The script defines the logic - what to look for, which items to act on, and what to do with them.

Scheduled automations check whether they're due roughly every 5 minutes. The time you configure follows your project's timezone, falling back to the workspace timezone, then UTC.

### Why your trigger isn't enough on its own

Triggers tell Plane _what type of event_ to watch for not which work items to care about. A "state changed" trigger fires for every single state change in the project, across every work item, regardless of type, priority, or who it's assigned to.
Triggers tell Plane _what type of event_ to watch for - not which work items to care about. A "state changed" trigger fires for every single state change in the project, across every work item, regardless of type, priority, or who it's assigned to.

Without conditions, an action like "set priority to Urgent" would run on every state change in the project. That's almost never what you want.

Conditions are what make an automation surgical. They let you say "only run this when the work item is a Bug, assigned to this person, with no due date set" whatever combination of criteria actually defines the case you're building for.
Conditions are what make an automation surgical. They let you say "only run this when the work item is a Bug, assigned to this person, with no due date set" - whatever combination of criteria actually defines the case you're building for.

One thing worth knowing: when a work item is first created, some fields like assignees and labels can take a moment to register, even if someone filled them in during creation. Plane handles this it checks the latest state of those fields before evaluating your conditions, so a filter like "assignee is X" on a creation trigger will work as expected.
One thing worth knowing: when a work item is first created, some fields like assignees and labels can take a moment to register, even if someone filled them in during creation. Plane handles this - it checks the latest state of those fields before evaluating your conditions, so a filter like "assignee is X" on a creation trigger will work as expected.

## Common use cases

Some common things people use automations for.

- **State management.** Automatically move work items through your workflow when something changes for example, transition a work item to "In Review" when an assignee is added, or back to "Backlog" when an assignee is removed.
- **State management.** Automatically move work items through your workflow when something changes - for example, transition a work item to "In Review" when an assignee is added, or back to "Backlog" when an assignee is removed.

- **Triage and routing.** Make sure new work lands in the right place without manual intervention for example, assign a default owner whenever a specific work item type is created, or apply a label to every incoming bug so nothing slips through untagged.
- **Triage and routing.** Make sure new work lands in the right place without manual intervention - for example, assign a default owner whenever a specific work item type is created, or apply a label to every incoming bug so nothing slips through untagged.

- **Priority escalation.** React to signals that indicate urgency for example, automatically mark a work item as Urgent when a specific label is applied, or raise priority when it gets reassigned to a senior team member.
- **Priority escalation.** React to signals that indicate urgency - for example, automatically mark a work item as Urgent when a specific label is applied, or raise priority when it gets reassigned to a senior team member.

- **Contextual reminders.** Surface the right information at the right moment for example, post an internal comment with a checklist when a work item enters "Ready for QA," or flag missing information when a work item is created without an assignee.
- **Contextual reminders.** Surface the right information at the right moment - for example, post an internal comment with a checklist when a work item enters "Ready for QA," or flag missing information when a work item is created without an assignee.

- **Scheduled operations.** Run scripts on a timer to handle things that don't map to a single event for example, sweep stale items weekly, sync data to an external tool nightly, or generate a status comment on open items every Monday morning.
- **Scheduled operations.** Run scripts on a timer to handle things that don't map to a single event - for example, sweep stale items weekly, sync data to an external tool nightly, or generate a status comment on open items every Monday morning.
2 changes: 1 addition & 1 deletion docs/automations/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Auto-close moves unfinished work items — those in Backlog, Unstarted, or Start
3. Set the **Auto-close work items that are inactive for** duration — for example, 1 month.
4. Choose the **Auto-close status** — the state that inactive work items will be moved to (e.g., Cancelled).

### Set up due date reminders <Badge type="warning" text="Enterprise Grid" />
### Set up due date reminders <Badge type="tip" text="Business" />

Plane sends in-app and email notifications to assignees and subscribers when a work item's due date is approaching.

Expand Down
2 changes: 1 addition & 1 deletion docs/core-concepts/issues/plane-query-language.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Plane Query Language
description: Filter work items using text-based queries with Plane Query Language (PQL).
---

# Plane Query Language (PQL) <Badge type="warning" text="Enterprise Grid" />
# Plane Query Language (PQL) <Badge type="info" text="Pro" />

Plane Query Language (PQL) lets you filter work items using text-based queries. Write structured expressions to quickly find exactly what you need.

Expand Down
2 changes: 1 addition & 1 deletion docs/core-concepts/pages/editor-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ Both modes feature a consistent toolbar with **Save** and **Exit** buttons, maki

Creates visually distinct sections with customizable icons and colors for highlighting warnings, tips , and calls-to-action.

## AI block <Badge type="info" text="Pro" />
## AI block <Badge type="tip" text="Business" />

Generate or transform content directly within your pages using AI. The AI Block lets you draft new content, summarize existing text, or run custom prompts without leaving the editor.

Expand Down
Loading
Loading