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

# Automations

> Set up Devin automations: event-driven workflows that start Devin sessions from Slack, GitHub, Linear, schedules, and webhooks.

Automations let you wire external events — Slack messages, GitHub webhooks, Linear ticket updates, schedules, and custom webhooks — to Devin sessions that start automatically. Instead of manually tagging Devin every time a bug is reported or a CI check fails, you define the trigger once and Devin handles each event as it arrives. You can also manage automations declaratively with the [Terraform provider](/api-reference/terraform-provider). For a video walkthrough with four examples, see the [Devin Automations tutorial](/tutorial-library/automations).

## Core concepts

An automation has a trigger and actions, with optional conditions and a Preflight check:

| Part | What it does |
| - | - |
| **Trigger** | The event that fires the automation (e.g. a Slack message in `#bugs`, a GitHub CI failure, a Linear label change) |
| **Conditions** | Optional filters that narrow the trigger (e.g. only fire when the label is `bug`, only for a specific repo) |
| **Preflight check** | An optional LLM filter or script that runs after an event matches, before the actions. It can skip the event or let it through; a script can also produce separate work items. |
| **Action** | What Devin does when the trigger fires — start a new session, message an existing session, or act as a triage monitor |

### Action types

| Action | Description |
| - | - |
| **Start session** | Creates a new Devin session with the prompt you define. The event payload is automatically included as context. |
| **Message session** | Sends a message to an existing, long-running Devin session — useful for feeding events into a session that maintains state. |
| **Triage Devin** | A persistent Devin that monitors a Slack channel. It watches every incoming message, decides what needs attention, and spawns child sub-devins for items that require investigation. See [Auto-triage](/product-guides/auto-triage) for details. For alerts, incidents, and bug reports, use [Devin Oncall](/product-guides/devin-oncall). |
| **Email notification** | Sends you an email when the automation runs — on every run, only on failures, or only on successes. |

### Trigger sources

| Source | Event types | Example use case |
| - | - | - |
| **Slack** | New message, reaction added | Triage bug reports in `#incidents`, react with 🚨 to start an investigation |
| **GitHub** | Issue, issue comment, PR opened/updated, PR review, check run (CI), push | Auto-fix CI failures, respond to `/devin` comments on issues |
| **GitLab** | Merge request, MR comment, issue, issue comment, push, pipeline | Auto-fix failing pipelines, respond to comments on merge requests |
| **Linear** | Issue created, label added, status changed, priority changed, assigned, moved to a team | Triage bugs when labeled, implement tickets when assigned to Devin |
| **Jira** | Issue created, issue updated, label added, status changed, assigned, commented | Implement tickets when assigned to Devin, track status changes |
| **Pylon** | Issue created, tag added, status changed | Triage customer bug tickets filed in Pylon. See the [Pylon integration](/integrations/pylon) |
| **PagerDuty** | Incident triggered, acknowledged, resolved, updated | Investigate high-urgency incidents as soon as they fire. See the [PagerDuty integration](/integrations/pagerduty) |
| **Schedule** | Recurring (cron-based) or one-time (run once) | Daily Sentry error sweeps, weekly dependency updates, nightly smoke tests, or a one-off task that runs at a specific future time |
| **Webhook** | Incoming HTTP request | Wire any external system (PagerDuty, Datadog, Sentry, custom tools) to Devin via a webhook URL |

Non-schedule sources appear in the trigger picker once the corresponding integration is connected in **Settings > Connections**.

A single automation can have **multiple triggers** — they act as an OR, so the automation fires when any of its triggers match. For example, you can have one automation that fires on both a GitHub CI failure and a Slack reaction.

## Creating an automation

### From the automations page

1. Navigate to **Automations** in the sidebar
2. Click **Create automation** and choose **Create** to open a blank editor (if you have no automations yet, click **Create manually** on the landing page instead). The same menu also offers **Template** (opens the template gallery) and **Generate with Devin** (starts a session that builds the automation with you)
3. Configure the trigger, conditions, and action
4. Click **Create automation**

### From a template

1. Navigate to **Automations** in the sidebar
2. Click **Create automation** > **Template** (if you have no automations yet, click **Create from template** on the landing page instead), or go directly to `/automations/templates`
3. Browse the template gallery — each template is a pre-configured automation for a common workflow
4. Click a template to pre-fill the editor with its trigger, action, and suggested limits
5. Customize the configuration (e.g. select your Slack channel or repo) and click **Create automation**

### Using natural language

On the automations page, click **Create automation** > **Generate with Devin** (if you have no automations yet, click the **Generate with Devin** card on the landing page instead). Devin opens a new session to help you build the automation. Describe what you want — for example, "When a CI check fails on my-org/my-repo, have Devin fix it and push to the same branch." Devin will generate the automation configuration for you, which you can review and create.

## Configuring triggers

### Slack triggers

Slack triggers fire when a message is posted or a reaction is added in a channel where Devin has been invited.

* **Slack message**: Fires on new messages. A channel condition is added by default; you can remove it to match messages across channels, but every condition group then needs at least one other filter (for example message text or sender type — **Include thread replies** alone is not enough).
* **User group mentioned**: Fires when a Slack user group (for example `@oncall`) is mentioned. Select the group or enter its Slack ID (starts with `S`), and optionally limit it to specific channels.
* **Slack reaction**: Fires when a specific emoji reaction is added to a message (e.g. 🚨 for incidents). You can filter by the reaction name and the channel.

<Note>For channel-scoped triggers, Devin must be invited to the Slack channel. You must also have your personal Slack account connected in **Settings > Connections > Slack**.</Note>

### GitHub triggers

GitHub triggers fire on repository events. You must select a specific repository for each trigger.

* **Issue**: Fires on issue events (opened, closed, reopened, edited, labeled).
* **Issue comment**: Fires when a comment is posted on a GitHub issue. Commonly used with a `starts_with "/devin"` condition so users can type `/devin` on any issue to trigger Devin.
* **Pull request**: Fires on PR events (opened, synchronized, etc.).
* **Pull request review**: Fires when a review is submitted on a PR.
* **Pull request review comment**: Fires on individual review comments.
* **Check run (CI)**: Fires when a CI check completes. Filter by `conclusion = failure` to auto-fix broken builds.
* **Push**: Fires on pushes to a branch.

<Note>By default, GitHub automations only fire on private repositories. An admin can opt an individual GitHub connection into public repositories: in [Settings → Connections → GitHub](https://app.devin.ai/settings/connections/github), open the connection's menu and set **Automation scope** to **All installed repos**. Anyone on the internet can comment on or open a PR against a public repo, so public-repo triggers carry a higher prompt-injection risk — enable this deliberately and keep your trigger conditions narrow.</Note>

### GitLab triggers

GitLab triggers fire on project events in your connected GitLab instance:

* **Merge request**: Fires on MR actions (opened, closed, merged, reopened, approved, updated).
* **MR comment**: Fires when a comment (note) is posted on a merge request, including diff review threads.
* **Issue**: Fires on issue actions (opened, closed, reopened, updated).
* **Issue comment**: Fires when a comment is posted on an issue.
* **Push**: Fires on pushes to a branch.
* **Pipeline**: Fires when a pipeline reaches a given status — filter by status (e.g. `failed`) to auto-fix failing pipelines.

### Linear triggers

Linear triggers fire on issue events in your connected Linear workspace. You must select a team for each trigger.

* **Issue created**: Fires when a new issue is created in the selected team.
* **Label added**: Fires when a label is applied to an issue (e.g. `bug`, `devin`).
* **Status changed**: Fires when an issue's status changes (e.g. moved to "In Progress").
* **Priority changed**: Fires when an issue's priority changes.
* **Assigned**: Fires when an issue is assigned to someone.
* **Issue moved**: Fires when an issue is moved to a different team — the trigger's team filter matches the destination team.

### Jira triggers

Jira triggers fire on issue events in your connected Jira site. You can filter by project, labels, status, assignee, and epic:

* **Issue created**: Fires when a new issue is created.
* **Issue updated**: Fires when an issue's fields change.
* **Label added**: Fires when a label is applied to an issue.
* **Status changed**: Fires when an issue's status changes.
* **Assigned**: Fires when an issue is assigned to someone.
* **Comment created or edited**: Fires when a comment is added or edited on an issue.

### Schedule triggers

Schedule triggers fire on a time-based schedule — either recurring or as a single one-time run. In the trigger dropdown, expand **Schedule** and choose **Every hour**, **Every day**, **Every week**, **Run once**, or **Custom schedule**.

* **Recurring**: Set the frequency (hourly, daily, weekly) and time. Under the hood, schedules use the iCalendar RRULE format. Choose **Custom schedule** to build a custom recurrence (repeat every N minutes/hours/days/weeks/months) or enter a raw RRULE string directly (e.g. `FREQ=WEEKLY;BYDAY=MO;BYHOUR=9;BYMINUTE=0`) for more complex cadences.
* **Run once**: Fires a single time at a specific future date and time, then automatically disables itself. Useful for one-off delayed work — e.g. "wake Devin up in 12 hours to run a task." Pick the date and time (defaults to one hour from now); it must be in the future.

<Tip>Each schedule has its own time zone, which defaults to your browser's time zone and can be changed in the schedule editor. The schedule runs at that local time, including across daylight saving changes.</Tip>

### Webhook triggers

Webhook triggers let you connect any external system to Devin via a unique HTTPS endpoint.

1. Create an automation with a **Webhook** trigger
2. Copy the webhook URL and secret shown in the trigger configuration
3. Configure your external system (PagerDuty, Datadog, Sentry, or any custom tool) to send HTTP POST requests to this URL
4. Optionally add a **payload filter** — a regex pattern that the request body must match for the automation to fire

Pass the webhook secret in any one of these ways:

* `X-Webhook-Secret: <secret>` header
* `Authorization: Bearer <secret>` header
* `?secret=<secret>` query parameter

Prefer a header — query strings are often captured in proxy, CDN, and server access logs.

The webhook payload is included in the Devin session prompt as context. Payloads larger than 200 KB are automatically truncated.

#### Webhook secret

Every webhook trigger has a secret that authenticates incoming requests — calls without the correct secret are rejected. The secret is generated for you and shown when you add the webhook trigger in the automation editor.

<Note>Copy the secret when it's shown — it will not be shown again. A lost secret cannot be recovered; regenerate it instead.</Note>

Each request must include the secret in the `X-Webhook-Secret` HTTP header. For example, to test with curl:

```bash theme={null}
curl -X POST '<webhook-url>' \
  -H 'Content-Type: application/json' \
  -H 'X-Webhook-Secret: <secret>' \
  -d '{"test": true}'
```

If you lose the secret or need to rotate it, open the webhook trigger in the automation editor and regenerate it. The old secret stops working immediately, so update your external system with the new value.

## Preflight checks

A **Preflight check** is an optional step that runs between a matched trigger and the automation's actions. An automation can have one of two kinds:

| Kind | What it does |
| - | - |
| **LLM filter** | A decision model reads each matched event and skips the ones that don't match your plain-language description. Fast and cost-effective. |
| **Script** | Your own Python, Node, or Bash code decides what happens: call an external service, keep state between runs, or start a session for each new item. |

To add one, click **Add a step before the agent runs** below the trigger section and choose **LLM filter** or **Run a script**.

<Note>Preflight scripts are being rolled out. If **Run a script** is not offered, scripts are not enabled for your organization yet.</Note>

<Warning>The automation's **Run now** button bypasses the Preflight check and runs the configured actions directly.</Warning>

### LLM filter

Select **LLM filter** and describe what events to filter in or not. For example: "PRs about the auth service", or "Slack messages about dinner".

The lightweight decision model reads the whole event. Only events that match will run the agent.

### Configure and test a Preflight script

The script runs in a separate, short-lived virtual machine (VM), not inside the Devin session it may start. It can read the event, keep a small amount of state between runs, and decide what work reaches the configured actions.

1. Create an automation or edit an existing one, and configure its triggers and conditions.
2. Click **Add a step before the agent runs** below the trigger section, and select **Run a script** in the **Before the agent runs** card.
3. Click **Edit script**, choose **Python**, **Node** (JavaScript), or **Bash** in the runtime selector, and edit the starter script.
4. If needed, use **Select secrets** in the script editor to attach organization secrets. Only the selected secrets are injected as environment variables. Saving or testing a script with attached secrets requires permission to manage organization secrets.
5. Set **Timeout (seconds)** in the card: the default is 60 seconds, and the allowed range is 1–300 seconds. The script uses the **Minimal environment** by default; if machine snapshots are available, the **Environment** selector also lets you choose an organization snapshot with your dependencies.
6. In the script editor, choose an event under **Test against** and click **Run**. You can test the unsaved script against a sample of a configured trigger, or against a recent event for an existing automation. Review the result, logs, and, for emitted items, the preview of how many would run, be duplicates, or be deferred.
7. Click **Save script** to apply the editor changes, then **Create automation** or save the automation to persist the configuration.

Test runs execute your script, but do not run the automation's actions, persist changes to its saved state, or mark emitted items as handled. Any external requests or side effects performed by your script are real. For example, testing a script that writes to an external service will still perform that write.

### Script input and output

The script receives these environment variables. Each contains a file path, not the JSON data itself:

| Variable | Contents |
| - | - |
| `EVENT_FILE` | Read-only JSON event with `event_type`, `source`, `payload`, and `received_at`. The `payload` shape depends on the trigger. |
| `STATE_FILE` | A read/write JSON object persisted between successful live runs, up to 64 KiB. Use it for a polling cursor, not a database. |
| `LAST_RUN_FILE` | Read-only feedback about previously emitted items: their `key`, `status`, and `session_id` when present. It contains up to the 200 most recent items and a `truncated` indicator. |
| `OUTPUT_FILE` | The JSON decision your script must write before exiting successfully. |

Write exactly one of `run` or `items` to `OUTPUT_FILE`, optionally with a string `reason`:

| Output | Behavior |
| - | - |
| `{"run": true}` | Run the configured actions once, with the original event. |
| `{"run": false, "reason": "Alert already resolved"}` | Skip the event without running its actions. |
| `{"items": [{"id": "INC-1", "title": "Investigate error spike"}]}` | Run the configured actions separately for each accepted item. With **Start session**, this starts one session per item; each session receives the original event plus that item as additional context. |
| `{"items": []}` | Skip the event because there is no work. |

For example, this Python script lets a Slack message through only if its text contains `urgent`:

```python theme={null}
import json
import os

with open(os.environ["EVENT_FILE"]) as f:
    event = json.load(f)

text = event.get("payload", {}).get("text", "")
should_run = "urgent" in text.lower()

with open(os.environ["OUTPUT_FILE"], "w") as f:
    json.dump({"run": should_run, "reason": "Urgency filter"}, f)
```

Select a Slack message sample or recent Slack message in **Test against** to inspect the result. Printing a decision to standard output is not enough: the script must write valid JSON to `OUTPUT_FILE` and exit with code 0.

### Script items, state, and limits

* **Duplicate prevention:** An item's `id` identifies a unit of work within this automation, not just an entity. `{"id": "INC-1"}` is handled once; add a `version`, such as the upstream update timestamp, to process a new occurrence of that incident. Without an `id`, Preflight identifies the item by a hash of its contents, so changing the contents can cause another run.
* **Per-run item cap:** By default, at most 10 new items are dispatched per run; the system's maximum cap is 50. Items beyond the cap are not handled and are not automatically scheduled. Your next script run must emit them again. Do not advance a cursor past deferred work just because it appeared in your output.
* **Previous outcomes:** Use `LAST_RUN_FILE` to distinguish running, succeeded, failed, or skipped work. An item whose run fails is released, so a later script run can emit it again.
* **Persistent state:** Live script runs for an automation execute one at a time. Failed scripts do not advance saved state or mark items as handled. **Clear state** clears both the saved JSON state and already-handled item history; previously handled items can run again after this reset.
* **Size limits:** Script source and output are each limited to 256 KiB, saved state to 64 KiB, and captured logs to 1 MiB.
* **Failures:** A nonzero exit, timeout, invalid output or state, or infrastructure failure stops that event before its actions. There is no automatic retry of the script for that event; a later trigger can run it again.
* **Network access:** The script's VM follows the automation's network restrictions and applicable [security profile](/product-guides/security-profiles). For example, polling an external alert service requires its host to be allowed. Attaching a secret does not grant network access.

## Configuring actions

### Start session

The most common action. When the trigger fires, Devin starts a new session with your prompt. The event payload (e.g. the Slack message text, GitHub webhook body, or Linear ticket details) is automatically appended to the prompt so Devin has full context.

Options:

* **Prompt**: The instructions Devin follows. Write this like you would a normal Devin prompt.
* **Playbook** (optional): Use `@playbook-name` in your prompt to include a [playbook](/product-guides/using-playbooks) for additional instructions.
* **Tags** (optional): Add tags to sessions created by this automation for easy filtering.

### Message session

Sends a message to an existing, long-running Devin session. Useful when you want a single persistent session to process events over time instead of spawning a new session for each event.

You must select the target session when configuring this action.

### Triage Devin (monitor)

Creates a persistent Devin session that monitors a Slack channel. See the [Auto-triage guide](/product-guides/auto-triage) for full details on this action type.

### Email notification

Sends an email notification when the automation runs. Choose when to notify:

* **Always** — on every invocation
* **On failure** — only when the session fails or errors
* **On success** — only when the session completes successfully

## Limits and safeguards

Automations include built-in controls to prevent runaway usage:

### ACU limit

Set a maximum ACU (Agent Compute Unit) budget per session started by this automation. If Devin hits the limit, the session stops. This prevents any single invocation from consuming excessive resources.

### Invocation limit

Set a cap on how many times the automation can fire within a time window. For example, "at most 10 invocations per hour" prevents a noisy Slack channel or a flurry of CI failures from spawning dozens of sessions.

Both fields are optional — if cleared, the automation runs without that limit. New automations start with no ACU limit and a **Rate limit** of 50 runs per hour (150 per hour for Slack channel-watching triage automations); templates apply the same defaults.

### Queueing

By default, every matching event starts a run right away. Turn on **Enable queueing** in the automation editor to limit how many runs happen at once:

* **Concurrent runs**: The maximum number of runs of this automation at one time. Extra events wait in the queue. A run stops counting toward the limit as soon as its session finishes and is waiting for new instructions.
* **Queue depth**: The maximum number of events that can wait in the queue. Events that arrive when the queue is full are dropped.

Queued runs appear with a **Queued** status in the automation's activity.

### Network policy

You can enable a network policy to restrict which external hosts the automation's sessions can access. This is especially important for automations that process untrusted user input (e.g. Slack messages, webhook payloads). You can add specific domains to the allowlist if Devin needs to reach external services. An automation's network policy only ever narrows access: it is intersected with the [security profile](/product-guides/security-profiles) governing the automation's sessions.

## MCP integrations

<Tip>Connecting MCP integrations is highly recommended — they dramatically improve automation quality by giving Devin access to runtime data like logs, metrics, and error details.</Tip>

Automations work with [MCP integrations](/work-with-devin/mcp) to give Devin access to external tools. When creating an automation, the **Connections** section shows which MCP servers are recommended and their connection status.

For example, the "Fix Sentry Errors Daily" template recommends the Sentry MCP so Devin can query Sentry for unresolved errors. The "Investigate Alerts Triggered" template recommends the Datadog MCP for pulling metrics and traces.

Enable MCP servers on the **Settings → Connections → MCPs** tab (or install their plugins from the plugin marketplace) before creating automations that need them.

## Slack tool access

By default, automation sessions can read and write to the Slack channels involved in the trigger. You can grant access to additional Slack channels in the **Slack tools** section of the automation editor. This is useful when Devin needs to read from multiple channels beyond the one that triggered the automation.

## Activity and monitoring

Each automation tracks its invocation history. On the automation detail page, the **Activity** tab shows:

* Recent invocations with timestamps
* Whether each invocation succeeded or was skipped
* Links to the Devin sessions that were created
* Error messages for failed invocations

The automations list page shows a sparkline for each automation, giving you a visual overview of activity over the past 30 days.

## Enabling and disabling

Toggle an automation on or off at any time from the automations list or detail page. Disabled automations stop processing events but retain their configuration. Re-enabling an automation resumes event processing immediately.

## Templates

Devin includes a library of pre-built automation templates for common workflows:

| Template | Category | What it does |
| - | - | - |
| Triage Bug Reports | Monitoring & Triage | Watches a Slack channel for bug reports — Devin triages each one, investigates the root cause, and replies in the thread |
| Triage Support Requests | Monitoring & Triage | Watches a support channel — Devin drafts an accurate reply in the thread and flags anything needing escalation |
| Triage Customer Bug Tickets | Monitoring & Triage | When a customer files an issue in Pylon, Devin reproduces the bug, investigates the codebase, and reports findings for the support team |
| Investigate Support Escalations | Monitoring & Triage | When support tags a Pylon issue for engineering, Devin finds the root cause, reproduces it, suggests a fix, and reports back in the internal Slack thread — tagging the likely owner and filing a Linear ticket if that's where escalations live |
| Investigate Alerts Triggered | Monitoring & Triage | When an alert lands in your Slack alerts channel, Devin uses the Datadog MCP to pull metrics, logs, and traces, then posts a root-cause analysis in the thread |
| Fix Sentry Errors Daily | Monitoring & Triage | Every morning, pulls the top unresolved Sentry errors, investigates each one, and opens fix PRs |
| Daily Error Report | Monitoring & Triage | Every morning, scans Datadog for new and spiking errors across your services and posts a concise report to Slack |
| Recurring Capacity Planning | Monitoring & Triage | On a schedule, reviews usage and resource-utilization trends to forecast capacity needs and flag services approaching their limits |
| Fix CI Failures | CI/CD & Release | Automatically fixes failing CI checks on non-Devin PRs — reads the build logs, identifies the root cause, pushes a fix, and verifies it passes |
| /devin Issue Fix | CI/CD & Release | When someone comments `/devin` on a GitHub issue, Devin investigates the codebase and opens a fix PR |
| Weekly Dependency Update | CI/CD & Release | Every Monday, scans for outdated packages, reviews changelogs for breaking changes, and opens update PRs grouped by risk level |
| Weekly Changelog | CI/CD & Release | Every Friday, compiles merged PRs into a categorized changelog and opens a PR updating CHANGELOG.md |
| Stale PR Cleanup | CI/CD & Release | Weekly scan for PRs not updated in over a week — checks for merge conflicts and posts a friendly nudge |
| Dependency Vulnerability Scanner | Security | Daily scan for known CVEs in your dependencies, prioritized by severity, with fix PRs |
| Secret Scanner | Security | Daily scan for leaked credentials, API keys, and tokens — replaces hardcoded secrets with environment variable references and opens fix PRs |
| Code Pattern Enforcer | Security | Weekly comparison of your repo against a golden reference repository, opening alignment PRs for deviations |
| OWASP Security Hardening | Security | Weekly scan for OWASP Top 10 vulnerabilities — injection flaws, XSS, missing auth checks, insecure defaults — with fix PRs |
| Cloudflare Security Audit | Security | Weekly review of Cloudflare audit logs to flag suspicious activity, configuration changes, and potential security issues |
| Weekly Status Digest | Project Management | Every Monday, compiles the past week's merged PRs into a concise status update and posts it to Notion |
| Sprint Progress Report | Project Management | A daily standup summary from Asana — pulls task status across projects and posts a progress update to Slack |
| Backlog Cleanup | Project Management | A weekly pass over your Linear backlog — closes stale and duplicate issues, flags untriaged ones, and fills in missing labels, priorities, and estimates |

To browse all templates, open the **Automations** page in the Devin app and click **Create automation** > **Template** (or go directly to `/automations/templates`).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.