Auto-Fix CI Failures
When the bot opens a PR and CI comes back red, the usual flow is for someone to read the failure, push a fix, and wait for CI again. This feature lets the bot do that round on its own — bounded by an attempt ceiling, gated on all checks finishing, and only ever for PRs the bot itself authored.
The feature is off by default and must be enabled per repo (or per org).
What it does
Section titled “What it does”When a check suite completes with at least one failing check on a PR the bot opened, the bot runs the coding agent against the PR’s head commit, lets it make code changes based on the failing job logs, and pushes the result as a new commit on the same branch. CI then runs again on the new commit. If it stays red and the budget is not spent, the bot tries again.
The bot only acts when all of these hold:
- The feature is enabled on the repo (or inherited from the org config).
- The PR was authored by the bot (PRs opened by humans are never touched).
- The PR is open, not in draft, and lives on the same repository (no forks).
- Every check on the PR head SHA is complete. A still-pending suite is skipped — the bot waits for the rest to finish and re-evaluates on the next event.
- At least one check finished red.
- The PR head SHA has not already been attempted by the bot.
- The attempt budget for the current window has not been spent.
Any unmet condition is a silent skip.
Configuration
Section titled “Configuration”Enable the feature from the dashboard’s repo or org Settings → Features tab. Toggle “Enable auto-fix CI failures” on and optionally set “Max attempts”.
The persisted shape is:
{ "autofixCIFailures": { "enabled": true, "maxAttempts": 3 }}| Field | Type | Description |
|---|---|---|
enabled | bool | Master switch. false disables the feature even if maxAttempts is set. |
maxAttempts | int (optional) | Number of consecutive bot fix attempts before the bot stops and leaves the PR for a human. Defaults to 3 when omitted. Range: 1–10. |
How the attempt budget works
Section titled “How the attempt budget works”maxAttempts counts consecutive bot fix attempts, not lifetime attempts. The counter resets whenever a human pushes a new commit to the PR branch. The mental model: the bot gets N tries between human interventions.
A few concrete cases:
- Bot opens a PR. CI fails. Bot fixes (attempt 1). CI fails again. Bot fixes (attempt 2). CI passes. The counter is moot now — CI is green.
- Bot opens a PR. CI fails three times in a row with
maxAttempts: 3. The bot stops and the PR sits red, waiting for a human. - Same situation, but you push a commit yourself before the bot has used the third attempt. The counter resets — the bot has a fresh budget of three more attempts starting from your commit.
- A commit with no associated GitHub author (rare, e.g. an unusual signing setup) does not reset the budget. The counter only resets when a real human login is on the commit.
How the bot picks what to fix
Section titled “How the bot picks what to fix”When the bot dispatches a fix, it:
- Lists every workflow run on the PR head SHA via the Actions API.
- Picks the runs that ended in
failureortimed_out. Other conclusions (cancelled,action_required,stale,neutral,skipped,success) are ignored — only a real CI failure starts a fix attempt. - For each, lists the jobs and downloads the logs of the ones that failed.
- Hands the last 5 KB of each failing job’s log (the tail is where the failure usually lives) to the coding agent, along with the workflow name and a link to the job.
- Caps the input at the first 5 failing jobs — repos with very wide failure surfaces would otherwise produce prompts too large to act on usefully.
If the failure surfaces only through a classic commit status or a third-party check that doesn’t expose itself as a workflow run, the bot has nothing concrete to read and leaves a message on the PR explaining it can’t auto-fix.
PRs the bot will not auto-fix
Section titled “PRs the bot will not auto-fix”- PRs authored by a human (even if you
@vgvbotthe bot to participate elsewhere on the PR). - Draft PRs.
- PRs from forks — the bot’s installation doesn’t have write access to the fork branch, so it can’t push a fix.
- PRs where any check is still running. The bot waits for everything to settle before acting.
- PRs where the bot has already attempted the current head SHA. If the previous attempt couldn’t fix the problem, the SHA is unchanged, and re-running the agent on the same revision would just spin.
- PRs that have already used their attempt budget in the current window.
Each of these results in a silent skip. The next time CI completes — or a new commit lands — the bot re-evaluates.
Known limitations
Section titled “Known limitations”- Non-Actions CI is invisible: the bot only reads failures from GitHub Actions. If your CI runs elsewhere (CircleCI, self-hosted Jenkins, etc.) and reports back via the classic status API or as a third-party check, the bot will see “CI failed” but find no failing jobs to inspect, and won’t try.
- Long failure logs are truncated: only the last 5 KB of each failing job’s log reaches the agent. Failures whose root cause sits far above the tail (e.g. a Java stack trace truncated mid-frame) may produce worse fixes.
- Cap of 5 failing jobs per attempt: in a wide failure (matrix build with many shards red), only the first 5 jobs feed the agent.
- No flake detection: the bot does not try to distinguish a real test failure from a flake. It will attempt to “fix” both. If your CI is flaky, you may see the bot land speculative changes; review them before merging.
- Workflow reruns are deduped by name: if the same workflow ran more than once on the same head SHA (e.g. a manual rerun of a flaky job), the bot only inspects the most recent run. Older reruns of the same workflow are dropped before the prompt is built, so duplicate failure context doesn’t crowd out other jobs.