Skip to content
Latchkey LogoLatchkey home

Cursor Agent CI and Copilot coding agents, wired into Actions

Cursor Agent CI and GitHub Copilot's coding agent look like the same problem and are not: one is a command you run inside a workflow you already own, and the other arrives with an ephemeral Actions environment of its own that you configure through a specially named file. Getting either wrong produces the same symptom, a pull request that sits there with no checks on it.

Two directions: an agent running as a step inside your workflow, and an agent whose pull requests enter yours
The two wiring problems this page covers, and which configuration file belongs to each. Behaviour read from both vendors docs on 2026-09-21.

There are two directions and they need different work. In the first the agent runs inside CI: a step in your workflow invokes it, with an API key and whatever permissions the job carries. In the second the agent runs somewhere else and its pull requests arrive at your CI, which is a question about triggers, approvals and trust rather than about installing anything.

Cursor is mostly the first. Copilot's coding agent is mostly the second, and it complicates things by also being powered by Actions at its own end. This page does each in turn and then the part they share.

Direction one: the agent as a step

The Cursor CLI is installed with a one-line script and then invoked in print mode, which its documentation describes as the non-interactive mode for scripts, CI pipelines or automation. Two lines of setup matter: the installer writes into $HOME/.cursor/bin, so that path has to be added to $GITHUB_PATH for later steps to find it, and the API key arrives as CURSOR_API_KEY from a repository secret.

What you do with it is the interesting choice. Running an agent to fix a failing build inside the same workflow that detected the failure is a tight loop and a poor idea on any repository accepting outside contributions, because the log it reads contains text a stranger wrote. Running it on a schedule against your own default branch, opening a pull request a human reviews, is the same capability with the blast radius removed.

.github/workflows/agent.yml, install and invocation quoted from the Cursor CLI GitHub Actions documentation
      - name: Install Cursor CLI
        run: |
          curl https://cursor.com/install -fsS | bash
          echo "$HOME/.cursor/bin" >> $GITHUB_PATH

      - name: Run Cursor Agent
        env:
          CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
        run: |
          agent -p "Your prompt here" --model gpt-5

What that step is allowed to touch

A step like the one above runs with the job's permissions and can read every secret the job can read, which is the whole security question in one sentence. Give the job the narrowest permissions block that lets it do its work, and keep the agent out of workflows triggered by events an outsider controls.

The rule that survives every variation of this: the log is data, never instructions. On a repository that takes pull requests from forks, a test name, an assertion message or a dependency's output was written by whoever opened the pull request, and you are about to hand it to something with write access to your tree. The trust boundaries for agent-authored changes are worked through in testing AI-generated pull requests in CI.

Direction two: Copilot brings its own environment

GitHub documents that while working on a task, Copilot has access to its own ephemeral development environment, powered by GitHub Actions, where it can explore your code, make changes, execute automated tests and linters and more. You configure that environment with a workflow file at a fixed path, .github/workflows/copilot-setup-steps.yml, and the job inside it has a required name.

The naming requirement is not a convention, it is the whole mechanism, and GitHub's own example carries the warning as a comment: the job MUST be called copilot-setup-steps or it will not be picked up by Copilot. Get it wrong and nothing errors; the agent simply starts with an environment it has to discover by trial and error, which the documentation itself calls slow and unreliable given the non-deterministic nature of large language models.

.github/workflows/copilot-setup-steps.yml, job name comment quoted from the GitHub Copilot documentation
name: Copilot setup steps
on: workflow_dispatch

jobs:
  # The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
  copilot-setup-steps:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v5
      - uses: actions/setup-node@v5
        with:
          node-version: 22
          cache: npm
      - run: npm ci

The gate that holds every agent pull request

This is the behavior that sends people to the issue tracker, and it is deliberate. GitHub documents that by default, Actions workflows will not run automatically when Copilot pushes changes to a pull request, because workflows can be privileged and have access to sensitive secrets. Somebody with write access clicks Approve and run workflows in the merge box, and only then does CI start.

The listed mitigations around it are worth knowing because they shape what an agent workflow can look like at all. Only users with write access can trigger the agent. It can push to exactly one branch. Its draft pull requests must be reviewed and merged by a human, and it can neither mark them ready for review nor approve or merge them. And when it opens a pull request under its own app identity, one more approval is required before merging on a repository that already requires at least one.

Runners: whose, and how big

Because Copilot's environment is Actions, the runs-on in copilot-setup-steps.yml decides what the agent works on, and it is billed like any other job. GitHub documents that the agent runs on a standard hosted runner, ubuntu-latest, by default, and that the same file can move it to larger runners, to self-hosted runners with access to internal resources, or to a Windows environment instead of the default Ubuntu Linux one.

Organization owners have a lever above that: a default runner type for every repository, set to either a standard GitHub runner or a labeled runner from a specific runner group, plus a switch for whether repositories may override it. If that switch is off, the runs-on in your setup steps file is ignored, which is worth checking before spending an afternoon on why a label had no effect.

QuestionCursor CLI in your workflowCopilot coding agent
Where does the agent run?A step in a job you wroteAn ephemeral environment powered by Actions
What configures it?The workflow file, like any step.github/workflows/copilot-setup-steps.yml
What authenticates it?CURSOR_API_KEY from a repository secretIts own token, issued by GitHub
Who picks the runner?You, in runs-onruns-on in the setup steps, unless the org locks it
Do checks run on its pull request?Whatever your triggers sayNot until someone clicks Approve and run workflows
Can it merge its own work?Only if you give it a token that canNo; a human must review and merge

What to actually run on an agent pull request

The same suite you run on a human one, plus two things that catch the specific mistakes models make. A lockfile check, because a dependency added without regenerating the lockfile is the most common agent-authored breakage and it fails much later than it should. And a diff-size or path guard, because the second most common is a refactor that quietly edits twenty files nobody asked about.

Everything else is ordinary. The value of a fast pipeline goes up sharply here, because an agent loop that waits twelve minutes for feedback is an agent loop that is mostly waiting, and the cost of a slow one is now paid per iteration rather than per human. That is the practical argument for the rest of the faster GitHub Actions material rather than a separate discipline.

What no run backs here

Nothing on this page was reproduced on a runner, and the reason is that both mechanisms need an account we would have to buy and an identity we would have to be. Copilot's approval gate lives in a merge box on a pull request opened by an app, and the Cursor step needs a paid API key; capturing either would produce a screenshot of our account rather than evidence about the product.

So every behavior above is quoted from the vendor documentation that defines it, read on 2026-09-21, with the two load-bearing strings, the required job name and the approval button, quoted rather than paraphrased because those are the two that a paraphrase would get subtly wrong. What a runner should hand an agent when a job does fail is a separate question with its own committed run, in CI failure reports your agent can read.

Frequently asked questions

How do I run the Cursor agent inside GitHub Actions?
Install the CLI in a step with curl https://cursor.com/install -fsS | bash, append $HOME/.cursor/bin to $GITHUB_PATH so later steps find it, then invoke it in print mode: agent -p "your prompt" --model <model>. Authentication is a CURSOR_API_KEY environment variable taken from a repository secret. Cursor documents print mode as the non-interactive mode for scripts, CI pipelines and automation.
Why do no checks run on a pull request opened by Copilot?
Because GitHub holds them by default. Its documentation states that Actions workflows will not run automatically when Copilot pushes changes to a pull request, since workflows can be privileged and have access to sensitive secrets. A user with write access clicks Approve and run workflows in the merge box to release them, and there is an optional setting to let them run without that intervention.
What is copilot-setup-steps.yml and what can it contain?
A workflow file at .github/workflows/copilot-setup-steps.yml that preinstalls tools and dependencies in Copilot's ephemeral environment. The job inside it must be named copilot-setup-steps or it is not picked up at all. GitHub lists six customizable keys on that job: steps, permissions, runs-on, services, snapshot and timeout-minutes, with a maximum of 59 minutes.
Can I put a coding agent on a larger or self-hosted runner?
For Copilot, yes, through runs-on in the setup steps file, which GitHub documents as the way to move from the default ubuntu-latest to larger runners, self-hosted runners with access to internal resources, or Windows. Organization owners can set a default runner type and disable repository-level overrides, in which case your runs-on is ignored. For a Cursor step, it is just a job, so runs-on works normally.

Related guides

References

Cursor or Copilot, a wasted turn costs the same. Latchkey hands the agent a report, not a log. Start free → 30-day trial · No credit card