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

# Auto-heal failing tests in CI

> Run the healing agent on every pull request to repair failing tests and open the fix as a PR.

After a run, [`momentic ai triage`](/cli-reference/momentic/commands/ai#triage)
investigates failed tests and repairs them in place. Based on your
organization's [Healing settings](https://app.momentic.ai/settings/healing), it
then opens a pull request with the fix.

<Note>
  This is the post-run repair agent. It is separate from in-run
  [auto-healing](/reliability/auto-heal) (locator resolution and smart waiting),
  which keeps a single run passing without changing your test files.
</Note>

## Add the workflow

Add a workflow to run your tests on every pull request and triage whatever
fails:

```yaml .github/workflows/momentic.yml theme={null}
name: Momentic

on:
  pull_request:

permissions:
  contents: write
  pull-requests: write

env:
  MOMENTIC_API_KEY: ${{ secrets.MOMENTIC_API_KEY }}

jobs:
  test-and-triage:
    runs-on: ubuntu-latest
    timeout-minutes: 20
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: "npm"

      - run: npm ci
      - run: npx momentic install-browsers chromium

      - name: Run tests
        continue-on-error: true
        run: npx momentic run --output-dir test-results

      - name: Triage failing tests
        if: always()
        run: npx momentic ai triage test-results --yes --timeout-minutes 10
```

`MOMENTIC_API_KEY` authenticates the run so the agent picks up your
organization's healing behavior.
[Create one here](https://app.momentic.ai/settings/api-keys) and add it as a
repository secret. `continue-on-error` on the test step lets the triage step run
even when tests fail, and `--timeout-minutes` caps total triage time. `--yes`
skips confirmation prompts (on by default when `CI` is set).

[Quarantined](/reliability/quarantine) tests are healed by default. Pass
`--skip-quarantined` to exclude them.

The triage step automatically uploads the updated local results archive after
processing, so the dashboard and connected reporting receive the final results
and validation signal. Pass `--no-upload` to keep the post-triage archive local.

The `contents: write` and `pull-requests: write` permissions let the
[Momentic GitHub App](/integrations/github) open the fix PR, which uses your
repository's
[pull request template](/integrations/github#pull-request-templates).

## Choose what a heal produces

Set **On successful heal** in
[Settings > Healing](https://app.momentic.ai/settings/healing) to control what a
successful repair produces:

* `pull-request`: open a PR with the fix (default). Best when you want the fix
  reviewed and merged like any other change.
* `draft-pull-request`: open the PR as a draft so a human verifies it before it
  is marked ready. Requires `momentic@2.123.0`+.
* `direct-commit`: commit the fix straight onto the branch under test, no PR.
  Writes through the [Momentic GitHub App](/integrations/github) server-side, so
  it works under a detached `HEAD` CI checkout and needs no `contents: write`.
  On a protected branch (e.g. `main`) it opens a draft PR instead.
* `patch`: print a `git apply`-ready diff instead of opening a PR. Needs no
  GitHub App or `pull-requests: write`, so it is the option for forked-PR runs
  or when you would rather apply the fix yourself.

**On failed heal** decides what happens to tests the agent cannot fix:

* `warn`: log the failures and keep the job passing. Use this while introducing
  auto-heal to an existing test suite.
* `fail`: exit `1` so the check blocks the PR once you trust it.
* `quarantine`: exit `1` for this run **and**
  [quarantine](/reliability/quarantine) the tests the agent could not fix.

## Skip triage when run is clean

Triage often needs your app's dev servers running (and browsers installed)
before it can re-run and repair tests - expensive setup to spin up on every PR.
When every non-quarantined run already passed cleanly there is nothing to
triage, so you can short-circuit all of that setup with
[`momentic results check`](/cli-reference/momentic/commands/results).

`results check` reads a finished results directory and exits `0` only when every
non-quarantined run passed cleanly - no failures, cancellations, in-run failure
recovery, or failure classifications. Any unclean run exits `1`. Gate the triage
setup on that signal:

```yaml .github/workflows/momentic.yml theme={null}
- name: Run tests
  continue-on-error: true
  run: npx momentic run --output-dir test-results

- name: Check whether triage is needed
  id: triage_check
  run: |
    if npx momentic results check test-results; then
      echo "needed=false" >> "$GITHUB_OUTPUT"
    else
      echo "needed=true" >> "$GITHUB_OUTPUT"
    fi

# Expensive setup only runs when something is actually broken.
- name: Start dev servers
  if: steps.triage_check.outputs.needed == 'true'
  run: npm run dev &

- name: Triage failing tests
  if: steps.triage_check.outputs.needed == 'true'
  run: npx momentic ai triage test-results --yes --timeout-minutes 10
```

On a clean run the `results check` step exits `0`, `needed` stays `false`, and
the dev-server and triage steps are skipped entirely. This is the same gate
Momentic uses in its own CI. See the
[`momentic results check`](/cli-reference/momentic/commands/results) reference
for `--json` output and the exact "clean" definition.

## Variations

For large test suites, run healing on a schedule or on demand instead of on
every PR by swapping the trigger. This mirrors the
[AI heal demo](https://github.com/momentic-ai/examples/blob/main/.github/workflows/test-ai-heal-demo.yml)
in [momentic-ai/examples](https://github.com/momentic-ai/examples):

```yaml theme={null}
on:
  workflow_dispatch:
  schedule:
    - cron: "0 9 * * 1" # every Monday at 09:00 UTC
```

Narrow the triage queue when you only want to touch some tests:

```bash theme={null}
# Only quarantined tests, two sessions in parallel
npx momentic ai triage test-results --only-quarantined --parallel 2

# Skip known-flaky tests by name
npx momentic ai triage test-results --exclude "checkout flow" "^Legacy "

# Preview the triage plan without healing or uploading the local archive
npx momentic ai triage test-results --dry-run --no-upload
```

`--dry-run` still uploads the local results archive by default. Combine it with
`--no-upload` to skip the archive upload.

See the [`momentic ai triage`](/cli-reference/momentic/commands/ai#triage)
reference for every flag. The same run-then-triage pattern works on
[GitLab CI](/running-tests/ci/gitlab-ci),
[CircleCI](/running-tests/ci/circleci), [Jenkins](/running-tests/ci/jenkins),
and [custom setups](/running-tests/ci/custom-setups).
