Skip to content

HomeDocsDeveloperGitHub agent

Developer

GitHub agent

Turn bug reports into pull requests in your own repository with a scheduled GitHub Actions workflow, and tell the reporter when you merge.

A bug reported in Reqio becomes a pull request in your repository, and merging that pull request tells the person who reported it that it is done. By default nothing needs approving first: the pull request itself is the thing you review.

The loop runs on reqio-app/feedback-to-pr, an open-source GitHub Action that lives in your repository, not in Reqio. The dashboard generates both workflow files for you, pre-filled, at Project > Settings > Agent.

Before you start

  • A Reqio project on any plan
  • A GitHub repository for that project's codebase
  • An API key for the coding agent's model

Runs on every plan, including Free

The loop authenticates with a project API key, and every plan can mint one. Free includes 100 API calls a day, enough for the default four-hour poll cadence and a handful of pull requests. Poll hourly, or point it at a busier backlog, and 100 calls a day is where you outgrow it: Pro raises the ceiling to 10,000 calls a day, Scale to 100,000.

Agent loop quota

The API-call quota above governs how often the workflow can ask Reqio whether there's work. A separate, monthly quota governs how many loops it can actually run: how many distinct requests get claimed for agent work.

Free10 / month
Resets on the calendar month, UTC.
Pro100 / month
More headroom than a small team runs through today. Resets on your billing anchor date.
Scale500 / month
Pooled across every project in your workspace, not per project. Resets on your billing anchor date.

What counts: a distinct request claimed for agent work, once per billing period. A repeat claim on a request already claimed this period, a draft pull request picking up more work, a resumed question round, never spends a second unit. Status changes and the notification that reaches the reporter are never counted here either, on any plan: metering completions would teach a team not to mark work done, which is the opposite of the point.

Hitting the cap never fails your CI

The claim endpoint always returns 200, on every plan, at every usage level. At the cap the workflow gets claimed: false, skips that one candidate, writes a single line to the job summary, and exits 0. Your pipeline goes green either way. You just don't get a pull request for that one report until the quota resets or you upgrade. See Agent loop claims for the full request and response shapes.

Migrating from v1 to v2

reqio-app/feedback-to-pr@v2 is the current action, and it is what Project > Settings > Agent generates today. v2 and v2.0.0 both point at it.

v1 is frozen on purpose and stays that way. It predates the claim endpoint and has no verify mode, so if you pass mode: verify to a workflow still pinned to @v1, nothing stops it from falling through to a real poll: it spends your model tokens and opens a pull request instead of running the free check you asked for. Do not repoint v1. Move to v2 instead.

If your workflow still says @v1, here is the migration in the order that avoids the confusing failure:

  1. Re-mint your project API key with agent:claim included, from Project > Settings > API keys (or regenerate the key from Project > Settings > Agent, which includes it by default). This is the step people miss, and it fails in a way that does not read as a scopes problem: verify comes back FAIL with POST /agent-claims failed: FORBIDDEN. That is the fix being named in the error - the key is missing a scope, nothing is broken.
  2. Point the workflow at @v2. Change uses: reqio-app/feedback-to-pr@v1 to @v2 in both .github/workflows/reqio-agent.yml and reqio-agent-merged.yml, or skip the manual edit and regenerate both files from Project > Settings > Agent, which always emits the current version.
  3. Run the workflow once by hand on Verify. Open the Actions tab, select Reqio agent, click Run workflow, and leave the mode input on its default, verify. It passes three checks in order: authenticate and list candidates, fetch one request's detail and screenshot, and reserve this month's quota as a dry run. It never invokes your model and never opens a pull request, so it costs nothing and is safe to re-run if step 1 needs another pass.

If you do nothing, your v1 workflow keeps working exactly as it does today. Reqio infers a loop from the first pull request it sees for each request, counts it separately from the metered total, and shows it to you - it never rejects a run for staying on v1. You are not broken. You are unmetered.

How the trigger works

This is the part people misunderstand, so it is worth being blunt about it. Nothing in Reqio pushes anything. Reqio holds no repository credentials and never sees your code. A scheduled workflow in your repository asks Reqio whether there is work waiting.

Trust runs one way: your CI reaches into Reqio, never the reverse. There is no stored token that could push to your default branch, because there is no stored token at all.

The cost is latency. GitHub's cron drifts by 10 to 40 minutes, and it stops running entirely after 60 days without a commit to the repository. For "a bug becomes a pull request" that is fine. The generated workflow also declares workflow_dispatch, so you get a Run workflow button whenever you do not want to wait for the schedule.

Private repositories and Actions minutes

Everything here works the same in a private repository. A public action can always be used from a private repo, and the workflow needs nothing extra.

The one difference is billing. Public repositories get unlimited free Actions minutes; private ones are metered, and GitHub rounds every job up to a whole minute. A poll that finds nothing to do exits in about three seconds and still costs a full minute.

That is why the schedule defaults to every four hours rather than hourly: roughly 180 billed minutes a month instead of 730, against the 2,000 included on the free tier. Tighten the cron if you want lower latency and have the minutes to spend.

Schedule
Every four hours by default, plus the manual Run workflow button.
Claim
The branch name is the claim: reqio/feature-{featureId}. A ready, merged or closed pull request means handled. A draft means unfinished, and the next run resumes it.
Scope
Anything self-describing, or anything a human briefed. Every bug qualifies on its own; any other category qualifies once someone writes the spec in Context.

Setup

  1. Open the Agent settings

    Go to Project > Settings > Agent and pick GitHub Actions. The page generates both workflow files with your project ID and base URL already filled in.

    The controls on that page (approval mode, completion kind, test command, pull requests per run) rewrite the generated YAML rather than saving anything server-side. The files in your repository are the only place this configuration lives.

  2. Mint an API key

    The workflow authenticates with a project API key. Mint one from the same page, or from Project > Settings > API keys, with exactly these five scopes:

    backlog:readscope
    Read the request, its context, and its screenshot.
    conversations:readscope
    Read the reporter's replies after your team relays a question.
    notes:writescope
    Write the pull request URL and any open questions to Context.
    status:writescope
    Move the request to In progress, and to Completed on merge.
    agent:claimscope
    Reserve one unit of the monthly agent-loop quota before the model runs. See Agent loop quota above.

    Note what is missing: conversations:write. The agent can never message a reporter. A human always relays.

    Actions still pinned to v1

    A workflow on reqio-app/feedback-to-pr@v1 never calls the claim endpoint, so minting agent:claim does nothing for it until you move to @v2. See Migrating from v1 to v2 for the three steps, in the order that avoids the confusing failure.

  3. Add two repository secrets

    Add both under Settings > Secrets and variables > Actions in your repository. The workflow reads them by name.

    SecretWhat it is
    REQIO_API_KEYThe project API key you just minted.
    model keyNamed after whichever agent you pick: ANTHROPIC_API_KEY for Claude Code, OPENAI_API_KEY for Codex, GEMINI_API_KEY for Gemini CLI, or your own name for anything else.

    The Coding agent control on the Agent settings page drives both the generated YAML and the name shown here, so the two can never disagree.

    The settings page shows you secret names, not fields to type keys into. Reqio never receives your model key and never sees your code: the agent reads that key inside your own runner, and the model never sees your Reqio key either.

  4. Commit the two workflow files

    Copy them into .github/workflows/reqio-agent.yml and .github/workflows/reqio-agent-merged.yml. The first is both the scheduled poll and the on-demand check: on its schedule trigger it looks for eligible requests and opens pull requests, and run by hand its mode input lets you choose Verify, a free dry run and the default, or Poll, the real thing. The second runs only when a pull request merges, and closes the loop.

  5. Let Actions open pull requests

    This one is easy to miss and it is the most common reason a first run appears to do nothing. In your repository, go to Settings > Actions > General > Workflow permissions and set:

    • Read and write permissions
    • Allow GitHub Actions to create and approve pull requests

    Both are off on every new repository, and a workflow file cannot override them. With them off the action pushes its branch and then fails at gh pr create, so you get a branch and no pull request.

    Organisation repositories

    If the repository belongs to an organisation, both controls appear greyed out on the repository page with nothing explaining why. Organisation policy is a ceiling: a repository may only be more restrictive than its organisation, never less. Set them at Organisation settings > Actions > General instead, then dial individual repositories back down if you want.

  6. Run the workflow once, on Verify

    Open the Actions tab, select Reqio agent (not the merge workflow), and click Run workflow. Leave the mode input on its default, Verify - it's the documented first thing to run, before the schedule or a by-hand Poll run ever does anything real.

    Verify exercises the real path end to end: it authenticates, lists candidates, fetches one request's detail and screenshot, and calls the claim endpoint with dryRun: true to check your scopes and read the current quota without reserving anything. It never invokes a model and never writes to Context. The dry-run claim call itself is what marks the project verified, server-side - that's what flips the Status region on the Agent settings page from "waiting for first run" to "setup verified." No separate event, nothing else to wire up.

    If it fails, fix what it reports and run it again; it costs nothing to retry. The most common failure is POST /agent-claims failed: FORBIDDEN, which means the key is missing agent:claim - see Migrating from v1 to v2 if that's you, or re-mint the key with that scope from Project > Settings > API keys either way.

What happens on a run

  1. The action lists eligible requests for your project: on the default auto-approve: false, only what your team moved to In progress. Turn it on and new reports count too.
  2. It keeps the ones in scope: every bug, plus anything of any category that has a human-written Context.
  3. It skips any whose pull request is ready, merged or closed. A draft is an unfinished attempt, not a claim, so a later run resumes it.
  4. It fetches the report, its conversation thread, and its screenshot, and assembles a brief.
  5. It claims one unit of the monthly agent-loop quota for this request, before invoking a model. If the claim comes back claimed: false (quota exhausted, or the agent is paused), it skips this one, writes a line to the job summary, and moves to the next candidate.
  6. It runs the coding agent in a checkout of your repository on a new branch.
  7. If you set test-command, it runs your suite and puts the result in the pull request body.
  8. It opens the pull request and writes the URL back to the request's Context, which confirms the claim.
  9. You review and merge in GitHub. Reqio builds no review UI.
  10. The merge workflow parses the feature id out of the branch name and marks the request Completed, which notifies the reporter.

Two approval modes

Default, auto-approve: false. Nothing is picked up until someone moves a request to In progress, and that move is the approval. There is no second confirmation on top of it. This is the default because a bug report is text a stranger wrote, and turning it into an agent prompt is a decision worth someone reading the report first.

auto-approve: true. New bug reports are picked up without anyone moving a card, and the pull request becomes the approval. This is the overnight mode: a bug reported at 2am is a pull request waiting for you at 9, rather than a card waiting for you to move it before anything can start. The agent moves the request to In progress when it begins, which tells the reporter work has started, so they are never told less than the truth. max-prs-per-run is the guard against a backlog flood turning into a review avalanche.

Either way, a feature request still waits for a human to write its Context. That is what makes it workable at all, and auto-approve does not substitute for it: with auto on, a request that already has a brief no longer needs the status move as well, but one without a brief is never picked up in either mode.

Nothing merges without you

Both modes end at a human. The default puts a gate before the agent runs as well as at the pull request; the other keeps only the pull request. Neither can merge anything: this action has no merge step at all.

What auto-approve costs before you turn it on

Every picked-up report spends model tokens and one agent loop from your monthly allowance, whether or not the pull request turns out to be good. Bug reports are also untrusted text written by strangers, and they become the agent's prompt. That is why the agent only ever gets contents: write and pull-requests: write, never runs on pull requests from forks, and never pushes to your default branch. If a burst of junk reports arrives, the pause toggle below stops new work immediately.

Pausing the agent

Project > Settings > Agent has a pause toggle, separate from anything in the workflow file. It takes effect immediately: there's no commit, no redeploy, nothing to push.

Pausing gates new claims only. The next poll finds work waiting, tries to claim it, and gets agent_paused back instead of a reservation, so it skips and moves on, the same as hitting the quota. Anything already claimed keeps going: an in-flight checkout finishes, a draft pull request with open questions is still readable and still resumes once your team answers, and a merge still completes the loop and notifies the reporter. Pausing stops the agent from picking up new work, not the work already underway.

Its purpose is a team working the backlog by hand for a while, without turning off the integration or editing the workflow file to do it.

When the agent lacks context

"The button is confusing" is not a specification. When the agent cannot reproduce or understand a report, it writes its questions, makes no code changes, and opens a draft pull request instead of guessing. A confident wrong pull request is worse than no pull request, and it is the fastest way to lose a reviewer's trust in the whole loop.

The questions appear in two places:

  • In the draft pull request, under an Open questions heading.
  • On the request in the dashboard, under a fixed heading in Context.

From the request in the dashboard your team can answer directly, or use Ask the reporter, which opens the reporter's thread with the agent's questions prefilled in the composer for you to edit before sending. The reporter's reply lands in the thread, and the next run reads it and resumes from the draft.

The team always decides whether a question reaches an end user. The agent never sends one itself.

If you swap in your own agent-command, the contract is a file at .reqio-agent/questions.md in the checkout: write it and make no code changes, and the action opens a draft rather than a normal pull request.

A run that fails outright is handled the same way. You get a draft pull request carrying the agent's log, never silence.

Either way the draft is picked up again on the next run: the branch is force-pushed over, the same pull request is updated in place, and it is marked ready once there is code and no open questions. Nothing has to be reopened by hand, and a transient failure such as a missing key does not cost you the request.

The agent gives up after three tries

Retrying is what makes a transient failure survivable, so retrying has to have an end. The action invokes a model at most three times on any one request. After that it skips it on every poll and says so in the log, until a person looks.

The count lives in the request's Context, in the agent's own section, as an Attempts: 2/3 line. Delete that line to give it another three.

This is the backstop for the case none of the other guards cover. A draft pull request is deliberately not a claim, so it stays retryable. The questions hold only engages if the agent actually wrote questions. A repeat claim is free, by design. None of that stops an agent that crashed, refused, or simply returned nothing, and a request in that state used to come back on every single poll, forever, spending your model tokens each time. Three failures is not a transient problem.

Raise or lower it with REQIO_MAX_ATTEMPTS in the workflow's env: if three is wrong for you.

Choosing an agent

Every one of these needs to be told not to wait for approval. None of them can ask a human mid-run, and a prompt that cannot be displayed is a refusal to edit anything, not a question. The presets on the settings page carry the right flag already.

AgentCommandSecret
Claude Codeclaude -p --permission-mode bypassPermissionsANTHROPIC_API_KEY
Codexcodex login --with-api-key then codex exec --dangerously-bypass-approvals-and-sandboxOPENAI_API_KEY
Gemini CLIgemini --approval-mode yolo --skip-trust -p "…"GEMINI_API_KEY

A few things caught us out and are worth knowing if you write your own command.

Codex does not read OPENAI_API_KEY on its own. Without codex login --with-api-key it sends no credential at all and fails with 401 Missing bearer. Piping the key in on stdin keeps it out of the process list.

Codex cannot use its own sandbox on a hosted runner. It uses bubblewrap, which needs CAP_NET_ADMIN to bring up a loopback interface, and GitHub-hosted runners do not grant it. Sandbox init fails and it refuses every filesystem command. Its bypass flag is documented for environments that are already externally sandboxed, which an ephemeral runner is.

Gemini needs a non-empty -p. It reads the brief from stdin and appends -p after it, but -p is also what selects headless mode. An empty one drops back to interactive and hangs the job until the timeout.

Gemini also needs --skip-trust, and --approval-mode yolo alone is not enough. A fresh CI checkout is never a trusted folder, so it silently overrides your approval mode back to default and then refuses to run at all, having just been told to auto-approve everything. Its auth is the easy part: unlike Codex it reads GEMINI_API_KEY straight from the environment.

Whichever agent you pick, give it a key on a paid plan. A free or heavily rate-limited key authenticates fine and then fails partway through a run, which costs you a draft pull request and a retry rather than a merge.

Your CI will not run on these pull requests

Read this before you turn the workflow on

GitHub deliberately suppresses workflow triggers for anything done with the default GITHUB_TOKEN, to stop workflows from triggering each other forever. So your own tests, linter, and type check do not run on the agent's branch.

Without a mitigation, a reviewer would be reading code your pipeline never touched. Set test-command and the action runs your suite inside its own job, before the pull request opens, and puts the result in the pull request body. That is the check the reviewer reads, and nothing untested reaches review.

Be clear about what that is worth: it is your suite, but it is not your CI, and the pull request body says so. If you need real check runs on the branch, pass a personal access token or a GitHub App installation token as github-token.

The merge workflow is unaffected, and this is verified rather than assumed: a human performs the merge, and human actions fire triggers even when the pull request itself was opened by the default token.

Inputs

InputDefaultWhat it does
project-idrequiredYour Reqio project id.
base-urlhttps://reqio.appReqio base URL, no trailing slash.
auto-approvefalsefalse: only requests your team moved to In progress. true: also picks up new bug reports on its own, and the pull request becomes the approval.
max-prs-per-run3Guard against a backlog flood turning into a review avalanche.
test-commandemptyRuns inside the agent's job before the pull request opens. See the caveat above.
allow-test-editsfalsefalse keeps the agent out of your test files.
agent-commandClaude Code headlessAny coding agent CLI that reads a brief on stdin and edits the checkout in place.
base-branchrepository defaultThe branch to cut from.
completion-kindNEXT_UPDATEMerge workflow only. SHIPPED if merging deploys for you, NEXT_UPDATE if it lands in a later release. This is what the reporter is told.

Safety

A report is text written by a stranger, and this feature turns it into an agent prompt next to repository write access. The design assumes that:

  • Everything a reporter typed is fenced and labelled as data in the brief, and the agent is told that instructions found inside the fence are to be reported, not followed.
  • The poll workflow asks for contents: write and pull-requests: write, and nothing else.
  • Neither workflow runs on fork-originated events, and the agent never pushes to your default branch.
  • With allow-test-edits: false, the default, any edit the agent makes to a test file is reverted before the commit. An agent that can edit the suite can make anything pass.
  • The API key is audience-bound to one Reqio project server-side. Presented against a different project it fails closed.

Turn on branch protection for your default branch. Human review is the only merge gate, and branch protection is what keeps it that way.

What to expect

Repositories without a test suite get noticeably worse results, because the agent has no way to check itself. If you have a suite, wire it into test-command.

What gets picked up

The rule is not "bugs". It is:

Anything self-describing, or anything a human has written a brief for.

A bug qualifies on arrival: it carries a screenshot, a page URL, and a context blob, so the report is the brief. Everything else is a wish until somebody writes the spec, and the place to write it is Context on the request. Fill that in and a feature request, a question, or a piece of feedback becomes workable, in exactly the same way.

That is deliberate. It keeps the gate on whether a human has said what to build, rather than on which category a visitor happened to pick in the widget.

Context is trusted input. The brief labels it as written by your team, and separates it from the reporter's own words, which are fenced and labelled as untrusted. So it is the right place for constraints, file pointers, and "do not touch X" instructions.