Skip to content
Get started

AI agents

Coding agents that run inside GitHub Actions are ordinary jobs, so moving them is the same one-line change. These are the setups we see most.

Why agents fit ephemeral runners

  • They run untrusted output. An agent executes code it just wrote. On Runloft that happens in a VM that is deleted when the job ends, so nothing it installs or leaves on disk reaches the next job.
  • They come in bursts. A review bot on every comment, or one agent per issue, means dozens of jobs at once. The default cap is 200 concurrent jobs per account, with no plan to upgrade.
  • They are long and spiky. Agent sessions run for minutes and spend much of that waiting on a model API. Per-second billing at $0.003 a minute keeps that idle time cheap; the CPU size only matters for the builds and tests the agent runs.

For most agent jobs, 4 vCPU is the right starting point: enough to install dependencies and run a test suite quickly, at half the per-minute cost of 8 vCPU.

Claude Code

Anthropic's claude-code-action responds to @claude mentions in issues and pull requests, or runs on a schedule with a prompt. Set runs-on on the job that uses it:

.github/workflows/claude.yml
name: Claude Code
on:
  issue_comment:
    types: [created]
  pull_request_review_comment:
    types: [created]

jobs:
  claude:
    if: contains(github.event.comment.body, '@claude')
    runs-on: runloft-ubuntu-24.04-4cpu
    permissions:
      contents: write
      pull-requests: write
      issues: write
      id-token: write
    steps:
      - uses: actions/checkout@v4
      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}

The API key stays a GitHub secret. GitHub passes it to the runner for that job only; it never goes through Runloft.

OpenAI Codex

The Codex GitHub Action runs Codex in a job, for reviews or for making changes. The same change applies:

.github/workflows/codex.yml
name: Codex review
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  codex:
    runs-on: runloft-ubuntu-24.04-4cpu
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - uses: openai/codex-action@v1
        with:
          openai-api-key: ${{ secrets.OPENAI_API_KEY }}
          prompt: Review this pull request and point out bugs.

GitHub Copilot coding agent

The Copilot coding agent runs its sessions in GitHub Actions and reads its environment from a special workflow, .github/workflows/copilot-setup-steps.yml, with a single job named copilot-setup-steps. The runs-on of that job decides where every Copilot session runs, so setting it to a Runloft label moves the agent itself:

.github/workflows/copilot-setup-steps.yml
# .github/workflows/copilot-setup-steps.yml
name: Copilot Setup Steps
on: workflow_dispatch

jobs:
  # The job must be named copilot-setup-steps.
  copilot-setup-steps:
    runs-on: runloft-ubuntu-24.04-4cpu
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci
  • The file has to be on the default branch to take effect.
  • Copilot requires Ubuntu x64 runners, so use one of the runloft-ubuntu-24.04 sizes, not arm64.
  • GitHub's agent firewall is designed around GitHub-hosted runners. If sessions fail to reach the network on self-hosted runners, review the firewall setting in the repository's Copilot coding agent settings.

Review bots on many pull requests

Comment-triggered workflows can fire far more often than CI. Two settings keep them under control:

  • A concurrency group per pull request, so a new comment cancels the previous run instead of stacking up behind it.
  • A monthly spend limit on the account, so a loop cannot run up a bill.
concurrency:
  group: review-${{ github.event.pull_request.number || github.event.issue.number }}
  cancel-in-progress: true