Code Review

Configuration YAML

Every field, type, and default in kind code_review pipeline files. No YAML is required to enable reviews; a file customizes reviewers, the gatekeeper, and budgets.

The field reference for kind: code_review pipeline files. One optional file customizes what the built-in review does: which pull requests it watches, which reviewers run, what the gatekeeper keeps, and what a review may spend.

No YAML required

Code review is enabled with one organization-wide setting, on the Settings tab of /reviews. With the setting on and no file committed, the built-in pipeline reviews every pull request: a description agent keeps the pull request description summarized, one reviewer reads the unreviewed commits and proposes findings, then a gatekeeper checks each claim against the code and decides what posts. Written out as YAML, the built-in pipeline is:

ellipsis:
  version: v1
  kind: code_review
  name: Code review
  description: Built-in incremental pull request review pipeline.

description:
  name: pr-description
  budget: 2.00
  claude:
    model: claude-sonnet-5
    system: |
      Maintain the summary section of this pull request's description:
      what the change does and where, in thirty seconds. Fold new
      commits into the existing summary rather than appending a
      changelog. Skip the update when nothing a reader cares about
      changed.

review:
  - name: bugs
    claude:
      model: claude-opus-5
      system: |
        Find the bugs in this change before they reach production.
        Read the diff, then read enough of the surrounding code to know
        whether each change is correct. Cover correctness, edge cases,
        error handling, concurrency, security, regressions in behavior
        callers depend on, and data or deploy hazards. Skip style,
        formatting, and naming. If you cannot name the input or state
        that produces a failure, it is not a finding.

filter:
  name: gatekeeper
  claude:
    model: claude-opus-5
    system: |
      Decide which proposed findings the author sees. Reject anything
      that does not hold against the code as it stands, is already
      handled elsewhere, is a style preference, or is speculative.
      Four sharp comments are worth more than twelve mediocre ones.

budget:
  run: 10.00

The system prompts above are abridged; the shipped ones are longer. Each prompt is the reviewing brain only: the commit range under review and the files each stage delivers through are supplied by Ellipsis, so a prompt never restates them. See Reviewers and Gatekeeper for what each stage does.

The pipeline file

A committed pipeline file is an overlay onto the built-in pipeline. It may replace any part: the reviewers, their prompts and models, the gatekeeper, the budget, the sandbox, and which pull requests are watched. Every field except ellipsis is optional, so the file declares only what it changes; a file that sets only budget: still runs the full built-in review.

The conventional path is agents/code_review.yaml, but any config directory works: ellipsis.kind: code_review is what identifies the file, not its location.

The merge rules:

  • A stage list replaces that stage wholesale. Declaring review: replaces the built-in reviewer; declaring filter: replaces the built-in gatekeeper; declaring description: replaces the built-in description agent.
  • An unset stage inherits the built-in one. A file with no review: runs the built-in reviewer.
  • An explicitly empty stage disables it. filter: [] runs no gatekeeper; description: [] never touches the pull request description; post_review: [] runs no post-review agents. Unset and empty mean different things.
  • include_default_reviewers: true is the exception: it keeps the built-in reviewer in front of your review: list instead of replacing it.
  • sandbox: and budget: merge field by field, so a file that only changes the image keeps the built-in reviewers.

Declaring pull_requests: makes its filters authoritative. A pull request the file does not match gets no review at all, rather than the built-in pipeline. The same goes for enabled: false: the file declares intent, so it suppresses the built-in pipeline rather than falling through to it. Which PRs get reviewed covers the filters and their matching rules.

A complete file, annotated:

ellipsis:
  version: v1
  kind: code_review        # what makes this file a review pipeline
  name: Backend review

pull_requests:             # authoritative: a PR this block does not
  repositories: [splitshift-api]   # match gets no review at all
  base: [main, "release/*"]
  draft: false

sandbox:                   # pipeline-wide defaults for every stage
  repositories:
    - name: splitshift-web # extra context repo; the PR's own repo is
                           # always cloned

include_default_reviewers: true   # keep the built-in reviewer, and add:

review:
  - name: migration-safety
    claude:
      system: |
        Review database migrations for production safety. Check for
        locking that blocks writes on large tables, missing backfills
        for new non-null columns, and rollout ordering that breaks if
        the migration and the code deploy out of order.
    pull_requests:
      paths: ["**/migrations/**"]   # this reviewer runs only when a
                                    # migration changes; otherwise it
                                    # costs nothing

filter:                    # replace the gatekeeper's prompt
  name: strict-gate
  claude:
    system: |
      Approve only findings a staff engineer would raise in review.
      Reject style opinions and anything a linter catches.

budget:
  run: 15.00               # one review, all stages together
  day: 100.00              # trailing caps: over budget means no
  week: 400.00             # reviews until the window rolls

Against this file, every splitshift-api pull request into main or a release branch gets the built-in review, migrations get a specialist pass on top, and a push storm cannot spend more than $100 in a day.

All fields

The top level of a pipeline file:

KeyTypeDefaultMeaning
ellipsismappingrequiredIdentity: kind, version, name, enabled.
pull_requestsmappingall pull requestsWhich pull requests the pipeline watches. Declaring it makes it authoritative.
sandboxmappingplatform defaultsPipeline-wide sandbox defaults, merged into every stage agent.
pre_reviewlist of stage agentsnoneContext agents that run before the reviewers.
descriptionone stage agent, or []the built-in description agentKeeps the pull request description's Ellipsis summary current. [] disables it.
reviewlist of stage agentsthe built-in reviewerThe reviewers. At most 8.
include_default_reviewersbooleanfalseKeep the built-in reviewer in front of your review: list.
filterone stage agent, or []the built-in gatekeeperThe gatekeeper. [] disables it.
post_reviewlist of stage agentsnoneAgents that run after the review posts.
budgetmappingrun: 10.00Spend caps in USD: per run, per trailing day, per trailing week.

Unknown fields are rejected, so a misspelled or misplaced key fails validation on push rather than being silently ignored.

ellipsis

FieldTypeDefaultMeaning
kindliteral code_reviewrequiredMarks the file as a review pipeline. Without it the file parses as an agent config and fails on the stage keys.
versionstringv1Config schema version. Only v1 is supported.
namestringunsetDisplay name in the reviews dashboard.
descriptionstringunsetDisplay description.
enabledbooleantruefalse skips the pipeline entirely. It still counts as intent, so it suppresses the built-in pipeline rather than falling through to it.
metadata.labelslist of strings[]Freeform tags for dashboard organization.
metadata.annotationsmap of strings{}Freeform key-value metadata.

pull_requests

Matched on every head advance of a pull request: the open, plus each later push. All declared filters must pass; an omitted filter passes everything.

FieldTypeDefaultMeaning
repositoriesrepository filterallThe watch set: which repositories' pull requests trigger reviews. A bare list is shorthand for include; exclude-only means all except those. Independent of sandbox.repositories.
baselist of strings[] (all)Target branch patterns: an exact name, a prefix glob like release/*, or the literal default.
headlist of strings[] (all)Source branch patterns, same forms.
draftbooleanunset (either)true reviews only drafts; false only non-drafts.
labelslist of strings[] (all)Review only pull requests carrying at least one of these labels, matched exactly including case.
pathslist of strings[] (all)Changed-file globs over the full pull request file set. Include-only: a negated pattern (!foo) is a validation error.
foraccount selectorhumans onlyWho may trigger a review, decided by the pull request author. users and bots each take true, a list of logins, false, or an include-minus-exclude mapping. Defaults: all humans, no bots.

The matching rules (glob forms, branch patterns, author semantics) with worked examples are in Which PRs get reviewed.

sandbox

Pipeline-wide sandbox defaults, applied to every stage agent's session. The same fields as a Cloud Agent's sandbox: block; each stage agent may declare its own sandbox, merged field by field onto this one.

FieldTypeDefaultMeaning
repositorieslist of {name, owner, ref}[]Extra repositories cloned into every stage sandbox for context. The pull request's own repository is always cloned.
variableslist of {name, value}[]Environment variables. With value set, an inline literal; without it, resolved by name from your stored sandbox variables, so secrets never enter the file.
compute.cpunumber1vCPU cores, 0.125 to 16, fractional allowed.
compute.memorystring or {gb}/{mb}4GBMemory, 512MB to 64GB.
compute.timeoutstring or {minutes}/{hours}1hMax session wall clock, 60s to 1h.
image.dockerfile_appendstringunsetRUN layers appended to the managed base image, built before any repository exists.
image.setupstringunsetA shell script run once at image-build time, after checkout, baked into the cached image. 600 second cap.
hooks.post_startstringunsetA shell script run on every session, after the container starts and before cloning. 300 second cap; a non-zero exit fails the session.
hooks.post_clonestringunsetA shell script run on every session, after all repositories are cloned. Same cap and failure behavior.
github.permissionsread_only or a scope mapinstallation permissionsNarrows the GitHub token every stage session gets, such as {contents: read, pull_requests: write}. Enforced by GitHub at token mint.
github.repositorieslist of stringsall sandbox reposNarrows which repositories the token may touch.
portslist of integers[3000, 5173, 8000, 8080]Accepted, but has no effect on review sessions, which end when the stage does.

Each field's full behavior (image caching, variable resolution, token scoping) is documented in the Cloud Agents configuration reference; the semantics are identical.

Stage agents

Every entry in pre_review, description, review, filter, and post_review is a stage agent, which runs as its own agent session:

FieldTypeDefaultMeaning
namestringrequiredUnique across the whole file. Attributes findings and titles the stage in the reviews dashboard.
claudemappingplatform defaultsModel and prompt; fields below.
sandboxmappingthe pipeline's sandboxThis agent's overrides, merged field by field onto the pipeline-level block.
skillslist of {path, repository}[]Claude Code skills installed for this agent, resolved from a repository directory containing a SKILL.md.
budgetnumber (USD)split evenlyThis agent's per-session cap. Agents without one split the remainder of budget.run.
pull_requestsmappingunset (all)This agent's own narrowing: base, head, and paths only.

The claude block:

FieldTypeDefaultMeaning
systemstring, {file} ref, or a list of bothrequiredThe agent's instructions. Must be non-empty for every stage agent; a {file: path} entry reads a repository file.
modelstringclaude-opus-5The model this agent runs on.
effortlow, medium, high, xhigh, maxmodel defaultReasoning effort.
fallback_modelstringunsetUsed when the primary model is overloaded.
max_turnsinteger > 0uncappedHard cap on agent turns. The budget still bounds the session.
settings{path, repository}unsetA Claude Code settings.json in a repository, applied to the session.

A stage agent's pull_requests decides which of the pipeline's pull requests this one agent reads. An agent that filters out costs nothing: no sandbox starts, and its share of the run budget goes to the agents that do run. repositories, labels, draft, and for are not accepted here; those scope the pipeline. See per-reviewer filters.

pre_review

Agents that run before the reviewers, one session each. Each writes context that is handed to every reviewer, and any one of them can cancel the review, a deliberate judgment that the range needs no review, which counts as coverage. By default none run.

pre_review:
  - name: linear-context
    claude:
      system: |
        Fetch the Linear issue this branch names and summarize its
        acceptance criteria for the reviewers.

description

One agent that keeps the pull request description's Ellipsis summary current. It runs after pre_review and before the reviewers, and Ellipsis applies its output to the pull request body the moment it finishes: the summary updates within the review, not after it.

The summary lives in a branded, marked section of the description. Ellipsis only ever rewrites between its own markers, so the author's text above and below survives every update. On every push the agent is shown the current summary and the new commits, and rewrites the summary to describe the pull request as it now stands. It can also conclude the current summary still holds and skip the update, or that the pull request should carry no summary, which removes the section.

Three shapes, like filter:

  • Unset: the built-in pr-description agent runs.
  • A single agent mapping: your description agent replaces the built-in one.
  • description: []: the pipeline never touches the pull request description.
description:
  name: pr-description
  claude:
    system: |
      Summarize the change for reviewers. Never mention documentation-only
      changes in the summary.

description is exactly one agent, not a list. A list with entries is a validation error; [] is the disable idiom.

review

The reviewers. Each reads the unreviewed commit range in its own sandbox and proposes findings; Ellipsis collects, deduplicates, and posts the survivors as one pull request review. Reviewers run in parallel, so several cost latency only once.

Declaring review: replaces the built-in reviewer wholesale. A pipeline may declare at most 8 reviewers, and each name must be unique across the file. A pipeline whose reviewers all filter out of a pull request reviews nothing on it: the review is cancelled, and the commits stay covered by the next review that runs.

See Reviewers for prompt guidance and worked examples.

include_default_reviewers

include_default_reviewers: true adds your reviewers to the built-in one instead of replacing it. The built-in runs first, then yours. The 8-reviewer cap counts both, and a declared agent may not reuse the built-in reviewer's name (bugs).

Use it when the built-in review is fine and you want one more pass alongside it. Without it, keeping the built-in review would mean copying its prompt into your file, where it stops tracking improvements to it.

Contradictory combinations are validation errors: include_default_reviewers: true with review: [] is rejected.

filter

The gatekeeper: one agent that judges every reviewer finding and decides what posts. Findings it rejects are recorded but never reach the pull request. Three shapes:

  • Unset: the built-in gatekeeper runs.
  • A single agent mapping: your gatekeeper replaces the built-in one.
  • filter: []: no gatekeeper runs, every reviewer finding posts unjudged, and the posted review says so.

filter is exactly one agent, not a list. A list with entries is a validation error; [] is the disable idiom.

filter: []

See Gatekeeper for tuning it.

post_review

Agents that run after the review posts, one session each. Use them for follow-up work such as notifications. A post_review failure never affects the posted review. By default none run.

budget

FieldTypeDefaultMeaning
runnumber (USD)10.00Caps one review: every stage agent of one pass, together.
daynumber (USD)1,000.00This pipeline's trailing 1-day spend cap.
weeknumber (USD)10,000.00This pipeline's trailing 7-day spend cap.

The day and week defaults are the platform ceilings; a value above the ceiling is lowered to it. When every stage agent declares its own budget, their sum must fit under budget.run; that contradiction is a validation error.

Budgets

Review budgets are three caps, each with a different failure mode.

budget.run caps one review end to end: every stage agent of one pass, together, not per stage. Each agent gets its declared budget if it set one; the agents that did not split the remainder evenly. An agent that hits its share stops where it is. The review still posts with the findings written by then, headed "Incomplete review" and stating that the remaining lines were not checked, because those commits count as covered and will not be re-read unless new commits land. Raise budget.run when reviews of large diffs stop early.

budget.day and budget.week are trailing windows over everything this pipeline spent, checked before a review starts. A pipeline at or over a cap reviews nothing until the window rolls; the skipped commits stay uncovered, so the next review that does run covers all of them. This is the guard against a push storm: forty pushes in an afternoon cannot turn into forty full-price reviews.

You can see what every review cost on the reviews dashboard, with a per-stage breakdown on each review's page, and on the API as the review's cost.

Review budgets are separate from session budgets. A Cloud Agent's budget.session caps one agent session, and its day/week/month fields cap one agent config's trailing spend; a review pipeline's budget.run spans several sessions in one review, and its trailing caps meter the pipeline. Both draw from the same account balance and count toward your account-wide spend limits. See code review budgets in Billing for how review spend is metered and billed.

budget:
  run: 25.00
  day: 100.00
  week: 400.00