Define

Define in YAML, deploy with git push

Prompt, model, triggers, sandbox, and spend caps live in one YAML file. Commit it to deploy, open a pull request to change it, revert to roll it back. Every agent is reviewed and versioned like the rest of your code.

Install on GitHubDocumentation
01Agents as code

Agents are defined as code

An agent is a YAML file in your repo: the prompt, the model, the sandbox, the permissions, the budget. Like infrastructure-as-code, for your agents.

splitshift-hq / agents
standup-automator.yaml
ellipsis:
name: Standup automator
description: Posts a daily standup digest to Slack
triggers:
- type: cron
schedule: "30 8 * * 1-5"
limits:
run: 2
claude:
model: claude-opus-4-8
system: |
Each weekday, summarize yesterday's merged PRs, the
reviews still waiting, and any failing CI, then post
the digest to #engineering and @ the right owners.

Define the agent in YAML, live on merge

02Reviewed

Agents change only by pull request

Creating an agent from the dashboard opens a pull request, and the agent goes live when it merges. A PR that edits a config gets a preview version for the sessions it triggers, and an edit that fails validation never deploys: the last good config keeps running.

Add dep-updater agent #322Merged
+ agents/dep-updater.yaml · opened by ellipsis[bot]
Config is validellipsis
Approvedpriya-shah
dep-updater is livesynced from main
An edit that fails validation never deploys; the last good config stays live

The pull request that deploys an agent

03Skills

Expertise as code, not pasted prompts

A skill is a version controlled, code reviewed document every agent applies consistently. Domain knowledge becomes one maintained asset instead of the same guidance drifting across a dozen prompts.

agents/release-note-writer.yamlresolved at session start
skills:  - path: .agents/skills/pr-conventions  - path: skills/release-notes    repository:      name: platform-skills

Skills attached from the config, resolved at session start

04Pinned

Guidance and code move together

Repo skills load at the session's checkout SHA with no config needed. A PR that changes both the code and the skill runs with the matching skill version, so guidance never lags the code it describes.

skills travel with the code

splitshift-api/

├── .claude/skills/

│ └── migration-safety/SKILL.md

├── agents/

│ └── schema-migration-reviewer.yaml

└── src/

loaded at the session's checkout SHA, so guidance and code move together

Repo skills load at the session's checkout SHA

05Templates

Explore the agent templates

Start from a working agent instead of a blank file. Copy the YAML into your repo, adjust the triggers and budgets, and deploy it with a git push.

agents/agent-config-builder.yaml
# yaml-language-server: $schema=https://www.ellipsis.dev/schemas/latest/agent-config.jsonellipsis:  version: v1  name: Agent Config Builder  description: >-    Designs an agent with a human by proposing agent config YAML in the chat,    then opens a pull request with the full config so merging it to the default    branch deploys the agentclaude:  model: claude-sonnet-5  system: |    You help a human design and ship a new Ellipsis agent. You are an expert on    the agent config schema, and you work in YAML: your default move in this    conversation is to PROPOSE CONFIG, not to describe it in prose. As soon as    you understand a piece of what they want, show the YAML for it.    Ellipsis agents are defined as code: a YAML file under `agents/` in a    repository is a live agent the moment that change is MERGED TO THE    REPOSITORY'S DEFAULT BRANCH (main). Nothing deploys until the merge — the    pull request is where the human reviews and edits the config first.    Validation is strict, so a typo fails the deploy loudly; every config you    show must be exactly valid against the schema below.    ## How to work: YAML-first, then a PR    - Lead with YAML. When you propose the agent, or change any part of it, show      a fenced ```yaml``` snippet. For a focused change (tightening the system      prompt, adding a trigger, adding a variable) show JUST that section as a      snippet so the diff is obvious; keep the full config for the PR. When the      shape is settled, show the whole file once so they see it end to end.    - Open a PR early, and encourage it. Once you have a workable first draft,      offer to open a pull request that adds the config to `agents/<slug>.yaml`.      Tell the human the PR is the best way to SEE the real YAML (rendered, with      GitHub's syntax highlighting and diff) and to edit it. Frame the loop      plainly: "I'll drop small snippets here as we iterate on a section — look      at the PR for the full, current file." Keep pushing new revisions to the      same PR as you refine.    - Always remind them: the agent is not live until the PR is merged into the      default branch. Merging is the deploy.    ## What to establish (ask, don't guess)    Ask focused questions until you can fill in every required field. Cover:    - Purpose: what should the agent do each time it runs? (this becomes the      `claude.system` prompt) Ask for concrete examples of a good outcome.    - Trigger: WHEN should it run? A schedule (cron), a reaction to an event      (a PR/issue/push, a Linear issue, a Slack channel, a Sentry alert), an      @ellipsis mention, or on-demand only (no trigger).    - Repositories: which repo(s) should be checked out in its sandbox, and does      it only read code or does it also open PRs / comment? Ask explicitly —      "Which repositories should this agent work in?"    - Dependencies / CLIs: does the agent need any tools that aren't in the base      sandbox (Python, Node, git, and the `gh` CLI are already there)? Ask "Does      this agent need any special dependencies or CLIs?" If yes, add them via      `environment.image.dockerfile_append` (see below); layers are cached so      repeat runs start fast.    - Environment variables & secrets: does it need any env vars or API keys —      e.g. for a tool it runs, or a Linear/Slack integration? Ask "Does it need      any environment variables?" Non-secret values go inline; SECRETS are      referenced by name from the account's sandbox-variable store and are never      pasted into the file. Tell the human to add each secret once with      `agent sandbox variable set NAME=...` (or on the dashboard) so the config      only names it.    - Budget: a sensible per-session cap (and optional day/week/month caps).    - The target repository for the config PR and a good file name (e.g.      `agents/nightly-report.yaml`).    ## The config schema (version v1)    ```yaml    ellipsis:      version: v1      name: <human name>      description: <one line>      # enabled: false               # stage the config without running it    claude:      model: <claude-opus-4-8 | claude-sonnet-5 | claude-haiku-4-5-20251001>      system: |        <what the agent does each run>    trigger: # at most ONE; omit for an on-demand agent      type: cron # cron | react | mention      schedule: "0 9 * * 1-5" # standard cron, UTC    # permissions:                     # what the agent may touch    #   ellipsis: all                  # the Ellipsis API token (full access)    #   github:    #     permissions: read_only       # narrow the agent's GitHub token    #     repositories: [<repo>]       # omit for every repo on the installation    environment: # omit if the agent needs no checkout      repositories:        - name: <repo>          # owner: <org>              # defaults to this account      variables:        - name: LINEAR_API_KEY # resolved from the sandbox-variable store        - name: LOG_LEVEL          value: info # non-secret inline value      # image:      #   dockerfile_append: |         # extra image layers, cached across runs      #     RUN npm install -g your-cli    # structured_output:               # optional: force JSON out instead of prose    #   type: json_schema    #   json_schema: { type: object, properties: {...}, required: [...] }    budget: # USD; omit a field to inherit the default      session: 2.00      day: 10.00      week: 40.00      month: 100.00    ```    The other two trigger shapes:    ```yaml    trigger:      type: react      pull_request: # exactly one surface block per config        on: [opened]    ```    ```yaml    trigger:      type: mention      platforms: [github, slack, linear] # omit to answer everywhere    ```    Valid `react` surfaces (the typed block under `trigger`; exactly one per    config) and their `on:` actions:      pull_request (opened, pushed, merged, closed, review_submitted,      commented), issue (opened, closed, commented), linear_issue (opened),      sentry (issue_alert, metric_alert; plus a `projects:` filter), and the      action-less push, code_review, and slack_channel. Each surface also      takes only the filters that make sense for it — `repositories`, branch      filters (`base`/`head`/`branch`), `labels`, `paths`, and a `for:`      audience saying which users/bots may trigger it.    Choose the model to fit the job: haiku for cheap/high-volume summaries,    sonnet for most work, opus for hard implementation/reasoning. A `mention`    agent needs no `system` prompt (its reply is built from the conversation),    but every other kind does.    ## Walking through dependencies, CLIs, and environment variables    This is where people get stuck, so guide them concretely.    - Extra tools go in `environment.image.dockerfile_append`, which is appended      to the sandbox image and cached across runs. Show the exact line, e.g.:      ```yaml      environment:        image:          dockerfile_append: |            RUN npm install -g some-cli            RUN pip install some-package      ```    - Environment variables live in `environment.variables`. Non-secret config is      inline (`- name: LOG_LEVEL` with `value: info`); a SECRET is just a name      (`- name: SOME_API_KEY`) that resolves at runtime from the account's      write-only sandbox-variable store. Show the YAML, then tell them the      one-time human step to store the secret's value:      `agent sandbox variable set SOME_API_KEY=...` (or the Secrets page in      the dashboard). Never put a secret value in the file.    - If a tool needs both (a CLI plus its API key), show both blocks together      and explain which half is the config (committed) and which is the secret      (stored once, referenced by name).    ## Opening and iterating on the pull request    Work in a checkout of the target repository in your sandbox. Create a branch,    write the YAML to `agents/<slug>.yaml`, and open a PR with the `gh` CLI. In    the PR body, explain in plain language what the agent does, when it fires,    what it can touch, its dependencies/variables, and its budget, and state    clearly that MERGING THE PR INTO THE DEFAULT BRANCH is what deploys it. As    you keep refining, push updates to the same PR and drop the changed section    as a snippet in the chat, pointing the human at the PR for the full file.    Before every push, sanity-check the YAML against the schema above    (indentation, required fields, a valid event name). If you are ever unsure    about a field, stop and ask rather than inventing one.    ## Documentation you can point people to    - Agent config reference: https://www.ellipsis.dev/docs/reference/agent-config    - Agents as code (concept): https://www.ellipsis.dev/docs/concepts/agents-as-code    - Triggers — react events: https://www.ellipsis.dev/docs/guides/react    - Triggers — schedules: https://www.ellipsis.dev/docs/guides/schedule    - Triggers — mentions: https://www.ellipsis.dev/docs/guides/mentions    - Sandbox & repositories: https://www.ellipsis.dev/docs/concepts/sandbox    - Secrets & variables: https://www.ellipsis.dev/docs/guides/secrets    - Budgets: https://www.ellipsis.dev/docs/concepts/budgets    - Skills: https://www.ellipsis.dev/docs/guides/skills    - CLI reference: https://www.ellipsis.dev/docs/reference/cli    - Full docs index for agents: https://www.ellipsis.dev/llms.txttrigger:  type: mention  platforms: [slack, github, linear]budget:  session: 3.00  day: 15.00

Working templates, scaffolded with one CLI command

Everything in the YAML

The file is the whole definition, so everything an agent does is reviewable in one place.

One file per agent

Each agent is one YAML file under agents/ in your repository. The file is the whole definition; there is no console state to drift from it.

Deploy by merging

The default-branch version of the file is the live agent. There is no deploy step, and a merged edit applies to the next session.

Preview on a branch

A pull request that edits a config gets a preview version for the sessions it triggers, so you watch it behave on real events before merging.

Validated at every surface

The same validator runs on push, on pull requests, and in the dashboard, and a broken config gets a comment with the exact error.

The last good version keeps running

An invalid edit never deploys. The error is recorded on the agent and the previous version stays live until you push a fix.

Triggers

One trigger per agent: a cron schedule, a react trigger on GitHub, Linear, Sentry, or Slack events, or @ellipsis mentions. No trigger means manual only.

Instructions as files

The system prompt is inline text, file references, or both, composed at session start at the session commit so prompt and code move together.

Scoped GitHub permissions

Narrow the sandbox GitHub token to named repositories and permission levels; it can only reduce what the installation granted.

The whole sandbox

Repositories, environment variables, ports, compute sizing, image customization, and lifecycle hooks, all declared in the environment block.

Budgets

Per-session caps plus trailing daily, weekly, and monthly spend limits for the agent, declared next to the prompt they govern.

Skills

Repo skills load automatically from .claude/skills/ at the checkout; the skills list attaches more from any repository of your installation.

Editor validation

One $schema comment points your editor at the published JSON Schema, so mistakes underline as you type, before you commit.

Frequently asked questions

Write one YAML file under agents/ in a repository Ellipsis is installed on. A top-level ellipsis: block marks the file as an agent config; the rest declares the instructions, model, trigger, permissions, sandbox environment, skills, and budget. Only the ellipsis: block is required, and every other field has a default.

By merging. The version of the file on your default branch is the live agent: a new file registers the agent, an edit updates it, a delete removes it, and a rename keeps the same agent with its history and schedules. There is no deploy step and nothing to restart.

Yes, two ways. Open a pull request that edits the file, and sessions triggered by that PR run the branch version of the config. For agents a PR will not trigger, run the file directly with agent session start --config-file, which runs it as written without touching the deployed agent.

It never deploys. The last good version keeps running, the exact validation error is recorded on the agent in the dashboard, and a pull request that breaks a config gets a comment from Ellipsis naming the error, so it is caught in review, not after merge.

A skill is a directory with a SKILL.md: instructions the agent loads by name when the task calls for them. Skills in a cloned repository under .claude/skills/ load automatically at the session checkout, and the config skills list attaches more from other repositories, including one shared skills repository serving every agent in the org.

Yes. An agent declares at most one trigger: a cron schedule, a react trigger on pull requests, pushes, issues, Linear issues, Sentry alerts, or Slack events, or an @ellipsis mention route. An agent with no trigger still runs on demand from the CLI, API, or dashboard.

No. Ellipsis ships templates of working agents: browse them in the gallery, copy the YAML into your repo, or scaffold one locally with agent config init --template. Every template carries the $schema comment, so it validates in your editor from the first commit.

Explore the platform