An agent has at most one trigger. Without one, it runs only when you start it from the dashboard or API. Each run starts a new session that stays open for follow-ups unless the agent sets `conversation.interactive` to `false`. For event triggers, the session's first message includes the event.

## Schedules

```yaml fragment
trigger:
  type: cron
  schedule: '0 9 * * 1-5'
```

Runs at 09:00 UTC on weekdays. `schedule` is a 5-field cron expression (minute, hour, day of month, month, day of week) in UTC:

```yaml fragment
trigger:
  type: cron
  schedule: '0 */6 * * *'
```

Runs every 6 hours, at 00:00, 06:00, 12:00, and 18:00 UTC. If Ellipsis is unavailable when a run is due, that run is skipped and the next one starts on schedule.

**Schedules** in the dashboard lists every agent with a schedule and when each runs next. A schedule's page lists its next runs and the sessions it started. `el agent list` shows the next run, and the API returns it as `next_run_at` on the agent (`GET /v1/agents/{id}`).

## Pull requests

```yaml fragment
trigger:
  type: react
  pull_request:
    on: [pushed]
    repositories: [api-repo]
    base: [main]
    draft: false
    paths: ['src/**', 'tests/**']
```

Runs on each push to a non-draft pull request into `main` that changes a matching path, including when the pull request opens.

| Event | When it fires |
| --- | --- |
| `opened` | Opened, reopened, or marked ready for review |
| `pushed` | New commits, including when the pull request opens |
| `merged` | Merged |
| `closed` | Closed without merging |
| `review_submitted` | A review is submitted |
| `commented` | A comment is added |

## Branch pushes

```yaml fragment
trigger:
  type: react
  push:
    repositories: [api-repo]
    branch: [default, 'release/*']
    paths: [package.json, package-lock.json]
```

Runs when a push to the default branch or a `release/` branch changes `package.json` or the lockfile. Push triggers have no `on` field.

## Issues

```yaml fragment
trigger:
  type: react
  issue:
    on: [opened]
    repositories: [api-repo]
    labels: [bug]
```

Runs when someone opens an issue labeled `bug` in `api-repo`.

## CI checks

```yaml fragment
trigger:
  type: react
  check_run:
    on: [failed, timed_out]
    repositories: [api-repo]
    names: ['test *', lint]
    branch: [default, 'release/*']
```

Runs when a check named `lint` or starting with `test ` fails or times out on the default branch or a `release/` branch of `api-repo`. A check is a GitHub Actions job or a check another CI app reports.

| Value | When it fires |
| --- | --- |
| `requested`, `queued`, `waiting`, `pending` | The check is created in that state |
| `started` | The check is created already running |
| `passed` | The check concludes `success` |
| `failed` | The check concludes `failure` |
| `timed_out`, `cancelled`, `skipped`, `neutral`, `action_required`, `stale` | The check concludes with that value |

- `names` matches check names exactly or by a prefix ending in `*`. Omit it to match every check
- `branch` is the branch the check ran on. A check on a fork's pull request has none
- `for` is the author of the commit the check ran on, so an agent's own commits don't count unless `bots` includes it
- Every matching check starts its own session, so a matrix of 20 failing jobs starts 20 sessions per agent. To run once when a whole workflow fails, use [workflow runs](#workflow-runs)
- A check on a commit that is no longer the head of its pull request starts nothing, so an agent never works on code that was already replaced

The session receives the check, its output, and the file annotations GitHub holds for it, plus the pull request it belongs to. For a GitHub Actions check it names the workflow run, so the session can read the job's log with `gh`.

The Ellipsis GitHub App needs the **Checks** permission on your installation. GitHub prompts the installation's owner to accept it, and until then Ellipsis receives no check events.

## Check suites

```yaml fragment
trigger:
  type: react
  check_suite:
    on: [failed]
    apps: [buildkite]
```

Runs once when every check Buildkite reported on a commit has finished and the suite failed. GitHub reports a suite only when it finishes, so `on` takes the finished values from [CI checks](#ci-checks) and `startup_failure`. `apps` matches the reporting app's slug, such as `github-actions`. `branch`, `for`, and the skip for a commit that is no longer the head of its pull request work as they do for checks. Needs the **Checks** permission.

## Workflow runs

```yaml fragment
trigger:
  type: react
  workflow_run:
    on: [failed]
    names: [CI]
    branch: [default]
```

Runs when the `CI` workflow fails on the default branch. `on` takes every [CI checks](#ci-checks) value and `startup_failure`. `queued` fires when a run is queued, `started` when it starts, and `action_required` when it waits for approval. `names` matches workflow names exactly or by a prefix ending in `*`. `branch`, `for`, and the skip for a commit that is no longer the head of its pull request work as they do for checks. The session can read the run's log with `gh`. Needs the **Actions** permission.

## Commit statuses

```yaml fragment
trigger:
  type: react
  status:
    on: [failed, errored]
    names: ['ci/circleci*']
```

Runs when a CircleCI status fails or errors. Some CI tools post commit statuses instead of checks. `on` takes `pending`, `passed`, `failed`, and `errored`. `names` matches the status context, its name on the pull request. `branch` matches when any branch GitHub lists for the commit matches. `for` and the skip for a commit that is no longer the head of its pull request work as they do for checks. Needs the **Commit statuses** permission.

## Releases

```yaml fragment
trigger:
  type: react
  release:
    on: [published]
    repositories: [api-repo]
    tag: ['v*']
    prerelease: false
```

Runs when a release whose tag starts with `v` is published in `api-repo`, skipping prereleases. A draft fires when it is published, not when it is saved; edits, deletions, and unpublishes never fire.

- `tag` matches tag names exactly or by a prefix ending in `*`; omit it to match every tag
- `prerelease: true` matches only prereleases and `false` only full releases; omit it to match both
- `for` is the release's author, so a release cut by CI or a release bot needs `bots` to include it

The session receives the release's tag, name, notes, target, author, and URL, and can read the release and the ones before it with `gh`.

## Repositories and authors

```yaml fragment
trigger:
  type: react
  pull_request:
    on: [opened]
    repositories:
      include: [api-repo, web-repo]
      exclude: [archived-repo]
    for:
      users: true
      bots: false
      teams: [platform]
```

Filters only decide which events match. They don't grant access or choose which repositories the session checks out; the environment does.

- An empty repository list matches every installed repository
- Branch filters accept exact names, prefixes ending in `*`, and `default`
- Labels match when any listed label is present
- Paths are globs of files to match; `!` patterns aren't allowed
- `teams` lists GitHub team slugs of the installed organization, `platform` for `@org/platform`; the author must pass `users` and be on one of the teams, and bots never are
- Every matching agent runs

A team named in `teams` must exist when the file syncs; a missing team is a sync error, and a personal account installation can't use `teams`. Membership is checked against GitHub each time an event matches, and members of child teams count.

## Linear issues

```yaml fragment
trigger:
  type: react
  linear_issue:
    on: [opened]
```

Runs when a person creates a Linear issue. Issues created by bots never count. The session receives the issue and, for a change, the values before and after it. Name the repositories it needs in `session.environment`.

| Event | When it fires |
| --- | --- |
| `opened` | An issue is created |
| `updated` | Every field listed in `changed` changes in one edit |

`updated` needs `changed`, which names the fields to watch. Each field takes `from` and `to`, the values before and after the change. Leave out `from` to match a change from any value, and `to` to match a change to any value. `labels` takes `added` and `removed` instead, because an issue holds several labels. `state` takes status names such as `In Review` or status types such as `started`, `assignee` takes member emails or `none`, `priority` takes `none`, `urgent`, `high`, `medium`, or `low`, and `project` takes project names or `none`. The [fields](/docs/agents/schema#fields) list every option.

The same names work as filters on the issue as it is after the event, alongside `team`, which takes team keys such as `WEB`. `assignee` as a filter also takes `any`.

```yaml fragment
trigger:
  type: react
  linear_issue:
    on: [updated]
    changed:
      state:
        from: [In Review]
        to: {exclude: [completed, canceled]}
```

Runs when a reviewer moves an issue out of In Review to any status that isn't finished, so the agent can read the review comments and fix its pull request.

```yaml fragment
trigger:
  type: react
  linear_issue:
    on: [updated]
    changed:
      labels:
        added: [agent]
```

Runs when someone adds the `agent` label to an issue, so a person hands work to the agent with one label.

```yaml fragment
trigger:
  type: react
  linear_issue:
    on: [updated]
    team: [WEB]
    assignee: none
    changed:
      state:
        to: [Ready for Agent]
```

Runs when an unassigned `WEB` issue moves into the Ready for Agent column from any status.

```yaml fragment
trigger:
  type: react
  linear_issue:
    on: [updated]
    project: [Checkout]
    changed:
      priority:
        to: [urgent]
    for:
      users: true
      bots: true
```

Runs when a person or an integration, such as an incident tool, raises a `Checkout` issue to urgent, so the agent starts investigating before anyone picks it up.

```yaml fragment
trigger:
  type: react
  linear_issue:
    on: [opened]
    team: [SUP]
    labels: [bug]
    project: {exclude: [Internal Tools]}
```

Runs when someone files a `SUP` issue labeled `bug` outside the Internal Tools project, so the agent tries to reproduce customer bugs as they arrive.

- Each filter takes one value, a list, or `include` and `exclude` lists, and matches when any listed value matches
- Every filter and every field in `changed` must match
- Status, label, and project names match exactly, and a name your Linear workspace doesn't have is a sync error
- `for` is the person who changed the issue, so a change by an integration such as GitHub counts only when `bots` includes it
- A change Ellipsis makes never starts a session, so an agent can't trigger itself
- Every matching issue starts its own session, so moving 50 issues at once starts 50 sessions per agent

## Slack channels

```yaml fragment
trigger:
  type: react
  slack_channel: {}
```

Runs when someone creates a Slack channel. The session receives the channel's name and purpose. To answer messages instead, use [Slack mentions](/docs/integrations/slack#mention-routing).

## Sentry alerts

```yaml fragment
trigger:
  type: react
  sentry:
    on: [issue_alert]
    projects: [api]
```

Runs when an issue alert fires in the `api` Sentry project. `on` accepts `issue_alert` and `metric_alert`; omit `projects` to match every project. A [`sentry.yaml`](/docs/integrations/sentry) file, when present, replaces these triggers.

## Pause a trigger

```yaml fragment
trigger:
  type: react
  enabled: false
  linear_issue:
    on: [opened]
```

Pauses the trigger and keeps its definition in the file: new Linear issues no longer start sessions, and nothing else changes. Starts from the dashboard, CLI, and API still work, and open sessions keep taking follow-ups. The dashboard shows the agent as **Trigger paused**. Set `enabled` back to `true`, or remove the line, to resume. A paused cron resumes at its next scheduled time and doesn't make up the runs it missed. To pause the whole agent, including starts, set `ellipsis.enabled: false`.

## Mentions

`@ellipsis` mentions are configured separately, in [GitHub](/docs/integrations/github), [Slack](/docs/integrations/slack), and [Linear](/docs/integrations/linear) handler files.
