# Required checks for AI pull requests: the same gates as a human

> Required checks for AI pull requests fail quietly when CI never reports. Set rulesets, check sources and reviews so agent PRs meet your gates.

Source: https://latchkey.dev/learn/agent-ci/required-checks-for-agent-pull-requests  
Updated: 2026-11-12

Required checks for AI pull requests only hold if CI actually reports on the agent's latest commit, from an event GitHub counts, set by the source you expect. Pin each required check to the GitHub Actions app, require an approval from someone other than the last pusher, put workflow files under CODEOWNERS, and make sure the agent's pull requests are created by an identity whose events start workflows.

A ruleset treats every pull request the same, which is what you want: the agent's branch merges on the same evidence as yours. The failures are all upstream of the ruleset. The check never started, it started from an event that does not count, it is waiting on a human, or it was set by something other than your CI.

Each of those looks like the same yellow dot in the merge box. The sections below separate them, starting with the one that has nothing to do with your ruleset at all.

## Why an agent pull request can have no checks

The first cause is the token. On github.com a pull request a workflow opens with `GITHUB_TOKEN` now gets its runs in an approval-required state, and a `push` with that token gets none; [testing AI-generated pull requests in CI](/learn/agent-ci/test-ai-generated-pull-requests-in-ci) has the rule and its exceptions.

The second is Copilot cloud agent, whose workflows by default do not run until a user with write access clicks Approve and run workflows. The third is quieter: checks from a workflow started by `workflow_dispatch` on the head branch do not appear on the pull request and do not satisfy a required status check, even if they pass on the same commit. Only `push`, `pull_request`, `pull_request_review`, `pull_request_target`, `deployment` and `deployment_status` count, plus `merge_group` for a merge queue.

| How the agent got its pull request | What the required check shows | Fix |
| --- | --- | --- |
| Workflow with `GITHUB_TOKEN` | Runs awaiting approval | App installation token or fine-grained PAT, or approve each run |
| Copilot cloud agent | Approve and run workflows in the merge box | Approve after review, or the Copilot setting to run automatically |
| Agent dispatches CI with `workflow_dispatch` | Waiting for status to be reported | Trigger CI on `pull_request` as well |
| Agent edits only paths your CI filters out | Pending, merge blocked | Do not require path-filtered workflows |

> Runs left awaiting approval for more than 30 days expire and are marked as failed, per GitHub's page on approving workflow runs from forks.

## A ruleset that pins the source of each check

Any person or integration with write access can set the state of any status check in the repository. That matters more with agents than with people: an agent holding a write-capable token can post a commit status named `test` with state `success`, and a ruleset that accepts any source counts it. Rulesets let you name the app that must report each check; for Actions that is the `github-actions` app, ID 15368.

The same ruleset can require the pull request rule with an approval from someone other than the last pusher, so whoever pushed last, an agent identity or a person, can never be the approval that covers that push. `strict_required_status_checks_policy` requires the branch to be up to date before merging, so the checks ran against the code that will actually land.

```Terminal
gh api --method POST repos/OWNER/REPO/rulesets --input - <<'EOF'
{
  "name": "main: same gates for everyone",
  "target": "branch",
  "enforcement": "active",
  "conditions": { "ref_name": { "include": ["~DEFAULT_BRANCH"], "exclude": [] } },
  "rules": [
    { "type": "pull_request", "parameters": {
        "required_approving_review_count": 1,
        "dismiss_stale_reviews_on_push": true,
        "require_code_owner_review": true,
        "require_last_push_approval": true,
        "required_review_thread_resolution": false } },
    { "type": "required_status_checks", "parameters": {
        "strict_required_status_checks_policy": true,
        "required_status_checks": [
          { "context": "test", "integration_id": 15368 },
          { "context": "lint", "integration_id": 15368 } ] } }
  ]
}
EOF
```

> Parameter names from the REST reference for repository rulesets. 15368 is the `id` returned by `GET /apps/github-actions`, read on 2026-11-12. The `context` must match the check name your job reports, which is the job name unless you set one.

## Reviews: who may approve agent work

Three settings decide whether a human actually looks. Require approval of the most recent reviewable push, so new commits from the agent after an approval need another one. Dismiss stale approvals when the diff changes, if you would rather start over than trust the last approver to re-read. And leave Allow GitHub Actions to create and approve pull requests switched off unless a workflow genuinely needs it: that setting is what decides whether a workflow's `GITHUB_TOKEN` can approve pull requests at all.

GitHub adds two Copilot-specific rules on top. The user who asked Copilot cloud agent for a pull request cannot approve it. And a ruleset requires one extra approval when Copilot opens a pull request under its own app identity rather than on behalf of a person; that setting is on by default, in public preview, and has no effect on rulesets that require zero approvals.

## CODEOWNERS for the files that change what CI means

An agent that edits `.github/workflows/` is editing its own examiner, and a lockfile or test config change alters what a green check proves. With code owner review required, any pull request touching an owned path needs an approval from one of its owners, who must have write access. The last matching pattern in the file wins, so put these lines at the end.

```.github/CODEOWNERS
# Changes to CI itself need a platform owner, whoever wrote them.
/.github/workflows/ @your-org/platform
/.github/CODEOWNERS @your-org/platform
package-lock.json @your-org/platform
```

## Checks that skip are checks that block

Agents produce narrow diffs, which makes path filters bite. A workflow skipped by a `paths` or `branches` filter leaves its required checks Pending, and the merge box waits with Waiting for status to be reported. A job skipped by its own `if:` condition reports Success instead. So require jobs that always run and decide inside, rather than whole workflows that sometimes do not.

The same logic covers the agent's own loop. A check the agent dispatched does not count, so let it dispatch for speed, but make the required run come from `pull_request`. If you use a merge queue, add `merge_group` too, or the queued pull request waits for a check that never starts. The full set of trigger rules for agent pull requests is on [testing AI-generated pull requests in CI](/learn/agent-ci/test-ai-generated-pull-requests-in-ci), and the approval banner itself on [waiting for approval to run workflows](/learn/github-actions/github-actions-waiting-for-approval-pr).

```.github/workflows/ci.yml
on:
  pull_request:
  merge_group:
jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      code: ${{ steps.filter.outputs.code }}
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - id: filter
        if: github.event_name == 'pull_request'
        run: |
          git fetch --no-tags --depth=1 origin "$GITHUB_BASE_REF"
          if git diff --name-only FETCH_HEAD HEAD | grep -qv '^docs/'; then
            echo "code=true" >> "$GITHUB_OUTPUT"
          fi
  test:
    needs: changes
    if: needs.changes.outputs.code == 'true' || github.event_name == 'merge_group'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
      - run: npm ci && npm test
```

> `GITHUB_BASE_REF` is only set on `pull_request` and `pull_request_target`, so the diff step runs only there and a `merge_group` run always tests. A job skipped by its `if:` reports Success, which is what keeps a docs-only pull request mergeable.

## What this page is built on

Documentation, read on 2026-11-12: the docs.github.com pages on required status checks, rulesets, `GITHUB_TOKEN` and Copilot cloud agent, GitHub's changelog, and the REST reference for the ruleset payload. No recorded run backs it and there is no evidence entry for it in this repository. The ruleset call above was not sent against a live repository from here, so check its response in your own before you rely on it.

## FAQ

### Why does my pull request say "Waiting for status to be reported"?

A required check has not reported on the latest commit. The usual causes are a workflow skipped by a path or branch filter, a run waiting for approval, or a check that only ran from `workflow_dispatch`, which GitHub does not evaluate for pull requests. Checks from earlier commits do not count.

### Why are workflows not running on a pull request created by GitHub Actions?

Because it was created with `GITHUB_TOKEN`. On github.com the `opened`, `synchronize` and `reopened` events now create runs that wait for approval from someone with write access. To have them start unattended, create or update the pull request with a GitHub App installation token or a personal access token.

### Can a bot approve its own pull request to satisfy required reviews?

Not if you configure against it. Require approval of the most recent reviewable push from someone other than the pusher, keep Allow GitHub Actions to create and approve pull requests off, and note that Copilot cloud agent cannot approve or merge, and the user who prompted it cannot approve its pull request.

### Do checks from workflow_dispatch count as required status checks?

No. GitHub only evaluates checks from workflow runs triggered by `push`, `pull_request`, `pull_request_review`, `pull_request_target`, `deployment` and `deployment_status`, plus `merge_group` for merge queues. A dispatched run can pass on the head commit and still leave the required check waiting.

## References

- [GitHub Docs: troubleshooting required status checks (read 2026-11-12)](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks)
- [GitHub Docs: available rules for rulesets](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets)
- [GitHub Docs: GITHUB_TOKEN, when it triggers workflow runs](https://docs.github.com/en/actions/concepts/security/github_token)
- [GitHub changelog: bot-created pull requests can run workflows if approved](https://github.blog/changelog/2026-06-11-bot-created-pull-requests-can-run-workflows-if-approved/)
- [GitHub Docs: Copilot cloud agent risks and mitigations](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/risks-and-mitigations)

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
