An automation has four top-level blocks: `ellipsis`, optional `trigger`, optional `input`, and `session`. Unknown fields fail validation.

## Scheduled test checks

```yaml title=".ellipsis/automations/nightly-tests.yaml"
ellipsis:
  name: nightly-tests
  description: Check the API test suite every night

trigger:
  type: cron
  schedule: '0 2 * * *'

session:
  harness:
    type: claude_code
    model: claude-sonnet-5
  instructions: |
    Run the tests in api-repo. Report failures with the test
    name and error. Do not modify code.
  environment:
    repositories:
      - name: api-repo
    hooks:
      after_checkout: |
        cd /sandbox/api-repo
        npm ci
  permissions:
    github:
      permissions: read_only
  budget:
    session: 3
    day: 10
    week: 50
```

The session records test results each night at 02:00 UTC.

## React to a pull request

```yaml title=".ellipsis/automations/check-api-changes.yaml"
ellipsis:
  name: check-api-changes

trigger:
  type: react
  pull_request:
    on: [pushed]
    repositories: [api-repo]
    paths: ['src/routes/**']
    draft: false

session:
  harness:
    type: claude_code
  instructions: |
    Check the changed API routes for missing test coverage.
    Add focused regression tests where needed, run them,
    and report the results.
  environment:
    repositories:
      - name: api-repo
    hooks:
      after_checkout: |
        cd /sandbox/api-repo
        npm ci
  budget:
    session: 5
```

A matching head update starts a session. Repository filters decide which events match; the environment decides which repositories are available.

## Typed input and output

```yaml title=".ellipsis/automations/classify-change.yaml"
ellipsis:
  name: classify-change

input:
  json_schema:
    type: object
    properties:
      description:
        type: string
    required: [description]
    additionalProperties: false
  message: 'Classify this change: {{description}}'

session:
  harness:
    type: claude_code
    model: claude-opus-5
  instructions: |
    Classify the requested change as bugfix, feature, or maintenance.
    Explain the classification in one sentence.
  output:
    json_schema:
      type: object
      properties:
        category:
          type: string
          enum: [bugfix, feature, maintenance]
        reason:
          type: string
      required: [category, reason]
      additionalProperties: false
  budget:
    session: 1
```

Invoke with `{"input":{"description":"Reject expired reset tokens"}}`. Read the validated result from `GET /v1/sessions/{session_id}/output`.

Structured output is available with every supported Claude and OpenAI model. Use the model's matching harness (`claude_code` or `codex`); `GET /v1/account/models` lists each model's capabilities. An invocation cannot provide both `input` and `prompt`.

## Repository instructions

```yaml title=".ellipsis/automations/backend-task.yaml"
ellipsis:
  name: backend-task

session:
  harness:
    type: claude_code
  instructions:
    - file: docs/engineering.md
      repository:
        name: api-repo
    - 'Run the relevant tests before finishing.'
  environment:
    repositories:
      - name: api-repo
  budget:
    session: 5
```

The session reads `docs/engineering.md` from `api-repo` and appends the inline instruction. Explicit repository references also work for API-managed automations.

## Codex skills

Declare a directory containing `SKILL.md` to give Codex a reusable procedure and its supporting files:

```yaml fragment
session:
  harness:
    type: codex
    model: gpt-5.6-terra
  instructions: Use the release-checks skill to review the release.
  skills:
    - path: skills/release-checks
      repository:
        name: api-repo
```

Codex receives the skill and can read its references or run its scripts. `SKILL.md` needs YAML frontmatter with a nonempty `description`; `name` defaults to the directory name and must fit 64 characters.

A skill uses the repository's checkout revision when that repository is in the session. Otherwise, `repository.ref` selects a revision, or the repository's default branch is used. A bare `path` uses the automation's source repository, falling back to the first session repository for inline configurations. Use an explicit repository for sessions without either.

Skills are resolved again when a session resumes. Missing files, inaccessible repositories, invalid metadata, and size-limit violations fail the session. Each skill allows up to 50 UTF-8 files, 64 KiB per file, and 512 KiB total. A session can declare up to 10 skills.

## Identity and triggers

| Field                  | Meaning                                                |
| ---------------------- | ------------------------------------------------------ |
| `ellipsis.name`        | Automation name, unique within the account             |
| `ellipsis.description` | Description shown in the dashboard                     |
| `ellipsis.enabled`     | Whether the definition is active                       |
| `ellipsis.metadata`    | `labels` and `annotations` for your own metadata       |
| `trigger`              | One cron or react trigger; omit for on-demand work     |
| `input.json_schema`    | Schema required of the invocation's `input`            |
| `input.message`        | Initial-message template; omit to render input as JSON |

In a template, `{{field}}` reads the caller's input. Triggered work can reference event fields with `{{field}}`. References must exist in the declared input or trigger schema.

## Session settings

| Field                                                  | Meaning                                               |
| ------------------------------------------------------ | ----------------------------------------------------- |
| `session.harness`                                      | Required tagged object, such as `{type: claude_code}` |
| `session.harness.model`                                | Model ID; Claude Code inherits the account default    |
| `session.instructions`                                 | Text, a repository file reference, or a list of both  |
| `session.environment`                                  | Saved environment name or inline environment          |
| `session.permissions`                                  | GitHub and Ellipsis access grants                     |
| `session.budget`                                       | Per-session and trailing automation spend limits      |
| `session.output.json_schema`                           | Schema for the final JSON result                      |
| `session.skills`                                       | Repository skill references for Codex                 |
| `session.harness.settings`, `effort`, `fallback_model` | Claude Code options, currently unavailable            |

See [Models](/docs/models), [Environment YAML](/docs/environment-configuration), and [Permissions](/docs/permissions).

## Budgets

```yaml fragment
session:
  harness:
    type: claude_code
  budget:
    session: 5
    day: 20
    week: 100
    month: 300
```

Values are US dollars. `day`, `week`, and `month` cover trailing 1-, 7-, and 28-day windows. They measure this automation's spend.

Handlers use the same `session.budget` fields in `slack.yaml`, `github.yaml`, `linear.yaml`, and `sentry.yaml`. A handler's trailing limits measure spend across all its sessions, including sessions started from earlier revisions of that handler. Each handler has its own limits. An omitted trailing limit inherits the same platform ceiling as an automation.

Account and developer limits also apply. Limits stop new paid requests; in-flight requests and sandbox teardown can add usage after a threshold is reached.
