Last reviewed: 2026-08-04
Direct answer
Merge queues for coding agent pull requests should be the final integration gate after review, not a replacement for review. A pull request can pass its own checks and still conflict with another change that reaches the target branch first. The GitLab merge trains documentation describes the exact failure: two merge requests can pass separately but break the target branch when their combined changes land.
A merge queue closes that gap by testing a temporary combined commit. On GitHub, the queue incorporates the latest target branch and the pull requests ahead of the current entry, then waits for the required checks on that merge group. The GitHub merge queue documentation
also makes an important configuration requirement explicit: GitHub Actions must respond to the merge_group event. A workflow limited to pull_request will leave the queue waiting for a required result that never arrives.
For GitHub Actions, the minimum event contract looks like this:
on:
pull_request:
merge_group:
Third-party CI needs an equivalent contract. GitHub documents temporary branches under the gh-readonly-queue/{base_branch} prefix, while the Buildkite merge queue guide
uses merge_group webhooks and can cancel builds for merge groups that no longer exist. Confirm which event and commit identity your CI provider expects before enforcing the queue.
Happy-path operator workflow
- Have the coding agent open a normal pull request from its isolated branch. Require a bounded description, named tests, and change scope notes before review begins.
- Run ordinary pull request checks and complete human review. The reviewer should approve the actual diff, not merely the agent’s summary. Use a consistent pull request review handoff when ownership changes.
- Add the approved pull request to the queue. Do not grant the coding agent a separate direct-merge path.
- Let the queue create a speculative commit containing the current target branch, the queued change, and any entries ahead of it.
- Run every required integration check against that speculative commit. Report the result against the merge-group commit, not the older pull request head.
- Merge only after the required checks succeed and all earlier queue dependencies are satisfied.
- Record the queue entry, tested commit, required-check results, and final outcome in an operator log.
Error-path operator workflow
- When a merge-group check fails or the combined commit conflicts, keep the pull request out of the target branch. Do not convert the failure into an automatic direct merge.
- Mark the failed queue entry with a stable failure class such as
combined-change-conflict,required-check-failed,infrastructure-failure, ortimeout. - Cancel or disregard downstream builds created from the obsolete queue composition. GitLab documents rebuilding later entries after a failed merge request is removed, and Buildkite documents cancellation of redundant merge-group builds.
- Preserve the failed merge-group commit identifier and the check output needed to reproduce the failure. Avoid logging full environment dumps or unrelated repository content.
- Route a product failure back to a focused agent follow-up. Route an infrastructure or flaky-test failure through a separate CI failure triage workflow so the agent does not rewrite application code to compensate for an unhealthy runner.
- After a corrective commit, rerun ordinary pull request checks and any required review. Then enqueue the updated pull request again.
- Treat the new queue result as new evidence. Do not reuse a successful status from an earlier pull request head or an invalidated merge group.
Who this is for
This workflow is for repository administrators, platform engineers, CI owners, and engineering leads whose coding agents can produce several review-ready pull requests against the same protected branch. It is especially relevant when the branch receives frequent merges, multiple changes become ready at similar times, or keeping the target branch green is an explicit requirement. Those are the conditions identified in the GitHub and GitLab documentation.
A low-volume repository with one carefully sequenced pull request at a time may not need a queue yet. Even there, documenting the event and status contracts makes later adoption less disruptive.
Key takeaways
- A green pull request check does not prove that several independently green changes work together.
- Queue checks must run on the speculative merge-group commit that could reach the target branch.
- On GitHub Actions, required workflows need the
merge_grouptrigger in addition to the normal pull request trigger. - Third-party CI must recognize the provider’s queue event or temporary branch and report status for the correct commit.
- A failed entry changes the composition of entries behind it, so obsolete builds must be canceled or ignored and later entries must be tested again.
- Queue enforcement should apply equally to agent-authored and human-authored changes targeting the protected branch.
- Human review, scope control, and queue validation solve different problems; keep all three.
Sources checked
- Managing a merge queue from GitHub Docs was checked for merge-group composition, required-check behavior, CI event requirements, queue settings, and removal after failed checks or conflicts.
- Merge trains from GitLab Docs was checked for the individually-green-but-incompatible failure case, cumulative testing, parallel train pipelines, removal of a failed entry, and regeneration of later pipelines.
- Using GitHub merge queues from Buildkite Documentation
was checked for third-party CI integration,
merge_groupwebhook handling, speculative commit identity, failed status reporting, and cancellation of invalidated builds.
All three public pages were reachable when this article was reviewed.
Contract details to verify
Write down the following contracts before you enable queue enforcement.
- Protected branch contract: Identify the exact target branches, required reviews, required checks, and merge method. GitHub notes that its merge queue cannot be enabled on a branch protection rule whose branch pattern uses a wildcard, so verify the actual provider configuration rather than assuming an existing broad rule will work.
- Event contract: Confirm which event creates queue builds. For GitHub Actions this is
merge_group. For a third-party provider it may be a merge-group webhook or a push for the provider’s temporary queue branch. - Commit contract: Record the speculative commit identifier received by CI and require status reports on that identifier. A check attached only to the pull request head is not evidence for the combined queue state.
- Check contract: List every result required to merge, including integration tests, policy checks, and any deployment preflight. Confirm that each check runs for both ordinary pull requests and queue entries when appropriate.
- Queue policy: Choose ordering, merge method, build concurrency, status timeout, and group limits deliberately. Start with conservative concurrency, then adjust using observed wait time, failure rate, and CI capacity.
- Failure contract: Define who owns product failures, merge conflicts, infrastructure failures, timeouts, and flaky checks. Specify which outcomes allow a retry and which require a new commit or renewed review.
- Bypass contract: Reserve any queue bypass for a documented incident path with an accountable approver. A bypass changes the tested composition and can force later queue work to restart.
- Agent handoff contract: Require the agent to name the changed surface, tests run, known omissions, and follow-up owner before the pull request is eligible for the queue.
Sanitized queue log
A useful queue log ties the pull request, speculative commit, CI run, and disposition together without copying prompts, diffs, environment values, or command output wholesale. A sanitized event can use fields like these:
{
"event_time": "2026-08-04T00:00:00Z",
"repository": "example/service",
"target_branch": "main",
"pull_request_number": 42,
"agent_label": "coding-agent",
"queue_entry_id": "mq-042",
"queue_position": 3,
"merge_group_sha": "abc1234",
"base_sha": "def5678",
"ci_run_id": "run-204",
"required_check": "integration",
"check_state": "failed",
"failure_class": "combined-change-conflict",
"dequeue_reason": "required-check-failed",
"retry_count": 0,
"correlation_id": "queue-042"
}
Keep field names stable across retries. Store detailed test artifacts in the CI system under its normal retention and access controls, then link them through internal identifiers rather than duplicating sensitive output in the queue log.
Failure modes
Required checks never start
The most common configuration error is enabling queue enforcement before CI listens for queue events. On GitHub Actions, a workflow that listens only to pull_request will not run for merge_group; the queue then waits for a required status that is never reported. Test the event path before making the queue mandatory.
CI tests the wrong commit
A pipeline may start successfully but check the pull request head instead of the speculative merge-group commit. This creates a convincing but invalid green status. Compare the commit recorded by the queue with the commit checked out by CI and the commit receiving the final status.
An obsolete build reports late
Removing or failing an earlier entry changes the combined commits behind it. A still-running downstream build now represents an obsolete composition. Cancel it where supported, or reject its status by commit identity. Never transfer that result to the replacement merge group.
One failure causes repeated queue churn
Rebuilding later entries after an earlier failure is expected because their combined state has changed. Blind retries can consume CI capacity without producing new evidence. Classify the failure first, fix deterministic product failures, and place bounded retry limits on infrastructure failures.
A bypass invalidates the queue’s assurance
A direct merge or emergency jump changes the base for every waiting entry. GitLab documents that an immediate merge can cancel and restart other train pipelines. Define whether emergencies restart the queue, pause it, or use a separate protected path, and test that policy before an incident.
Flaky checks are treated as code incompatibility
A flaky required check can repeatedly remove healthy changes, while ignoring the check can admit a real incompatibility. Track flaky outcomes separately from product failures. Keep the required-check policy explicit and fix recurring instability rather than teaching the coding agent to make unrelated code changes until a run happens to pass.
The queue becomes a substitute for review
A merge queue validates a combined repository state. It does not establish that the requested change is appropriate, the diff is understandable, or the agent stayed within scope. Keep review approval and queue eligibility as separate states.
FAQ
Is ordinary pull request CI enough?
Not when multiple changes can merge close together. Ordinary CI may test each pull request against a different target-branch state. A merge queue adds a check of the exact combined state represented by the speculative queue commit.
Does a merge queue repair conflicts automatically?
No. It can prevent a failing or conflicting combination from reaching the target branch and can reconstruct later queue entries after one is removed. The underlying code or conflict still needs a focused correction before the pull request is queued again.
Should an agent continuously rebase while it waits?
Do not make repeated rebasing the default solely to chase branch freshness. The queue’s purpose is to test the approved change against the latest target and earlier queued entries. Resolve explicit conflicts and follow your review policy when a rebase changes the reviewed diff.
How much queue concurrency should we enable?
There is no universal value. Begin low enough that a composition change does not invalidate an unaffordable number of builds. Increase concurrency only after measuring queue wait time, CI duration, cancellation volume, and failure causes.
Can human and agent pull requests share one queue?
Yes, and a single protected-branch policy is usually easier to audit. The queue validates change combinations regardless of authorship. Labels can still identify agent-authored changes for reporting and review routing without creating a weaker merge path.
What evidence should be retained after a failure?
Retain the pull request number, queue entry, target and speculative commit identifiers, required-check name, CI run identifier, failure class, dequeue reason, and retry count. That is enough to reconstruct the decision without placing full prompts or broad environment output in the operator log.
Reader next step
Run a two-pull-request canary on a non-production repository or protected test branch. Add the queue event to CI, require one deterministic integration check, and enqueue two small reviewed changes whose combination causes a safe test failure. Verify that the first valid entry can proceed, the incompatible entry cannot merge, obsolete downstream work is canceled or rejected, and the reconstructed entry receives a fresh check.
Then document the happy path, the failure owner, the retry limit, and the bypass rule beside your existing branch policy. Once both paths have produced the expected logs and status checks, enable the queue on one busy branch and review its wait time and failure classifications before expanding it further.