agent-gate-loop
September 17, 2026 · View on GitHub
A GitHub Action that turns an issue into a pull request. An AI agent writes the change, and a gate checks it before a human sees it. The gate has four parts:
- Guards. No edits to protected paths, no deleted tests, a size limit, and at least one change.
- Your checks. Your own typecheck, lint and test commands.
- Reviewer. A separate, read-only Claude session that lists findings.
- Jev (TypeSafe). Checks each finding, and asks whether the change does what the issue asked, whether it touches unrelated code, and how good the tests are.
If the gate fails, the agent gets one merged feedback note and tries again, up to max_rounds.
If Jev is unsure, the loop stops and a human decides. The action never merges.
issue ─► Jev intake ─► fixer ─► guards ─► checks ─► reviewer ─► Jev gate ─► decide
▲ │
└──────────── feedback (on fail) ◄─────────────────┘
pass / escalate / out of rounds ─► PR + report
Use it
Copy examples/consumer.yml to .github/workflows/agent.yml, then add
the repository secret TYPESAFE_API_KEY plus either ANTHROPIC_API_KEY (pay-per-use) or
CLAUDE_CODE_OAUTH_TOKEN (Claude subscription, from claude setup-token). These are the same
names Claude Code's GitHub setup uses. If both are set, the API key is used. To start a run, label an issue
agent:run or comment /agent on it. Only people with write access can trigger runs.
In the repo's Settings → Actions → General, turn on Allow GitHub Actions to create and approve pull requests. Without it, the default token cannot open the PR.
Prototype. Known gaps before unattended use: the agent can still change
.git/configthrough its shell, and check commands can read the job's GitHub token and TypeSafe key from the parent process. Use it only on issues written by people you trust.
Checks run before each commit, and the agent commits every non-ignored file in the working tree.
Make sure build output and coverage folders are listed in .gitignore, or they will end up in the
diff and the PR.
For a different toolchain, call the action directly from your own job, after your setup steps:
- uses: actions/checkout@v5
with: { fetch-depth: 0, persist-credentials: false }
- uses: Ripwords/agent-gate-loop@main
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} # or:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
typesafe_api_key: ${{ secrets.TYPESAFE_API_KEY }}
checks: |
go test ./...
See action.yml for every input.
Results
| Result | Meaning | PR |
|---|---|---|
passed | Every gate passed | ready for review, unless the issue is high risk |
escalated | Jev was unsure, or the reviewer failed | draft |
failed | Out of rounds or budget, or the same problems repeated | draft |
needs-info | The issue is too vague | none; the action comments on the issue |
Cost controls
The loop is built to spend as little as possible:
- Cheap gates first. Guards, your checks, and a single Jev pre-check call run before any AI reviewer. If Jev is confident the change misses the issue, adds unrelated edits, or has no tests, the reviewer is skipped.
- Right-sized models. The fixer uses
claude-sonnet-5. The reviewer (reviewer_model: auto) usesclaude-haiku-4-5for small changes (≤small_diff_filesfiles and ≤small_diff_lineslines) andclaude-sonnet-5otherwise. - Hard caps.
max_rounds(default 2) andmax_cost_usd(default 2) stop the loop. The remaining budget is passed to each agent session as its spend limit.max_cost_usdcounts Claude spend only; TypeSafe (Jev) calls are billed separately and are not included. - The fixer keeps its context between rounds instead of re-reading the repo.
- Your repo's rules, for free.
review_shortlistpoints at a JSON file of grep rules run on the added lines:hardrules fail the round with the rule's fix text,judgementrules go to the reviewer as things to check.review_rubricpoints at a markdown rubric that the reviewer follows. Both are read from the base commit.
with:
review_shortlist: .claude/review-shortlist.json
review_rubric: docs/evals/review-pr/rubric.md
Security notes
- Use a spend-limited Anthropic key. The agent's shell runs in the same process that holds the credential. A subscription token cannot be spend-limited, and a leak exposes your whole Claude plan.
- The agent never receives the TypeSafe key or the GitHub token. Check commands receive no secret-looking environment variables.
- A PR opened with the default
GITHUB_TOKENdoes not trigger your other workflows. To run CI on agent PRs, passAGENT_GITHUB_TOKEN. - On private repos without draft PR support, non-passing runs open a normal PR marked by the
agent:*label instead of a draft.
Run locally
ni
cp .env.example .env.local
nr e2e # runs the loop on examples/sample-repo
nr local --repo ../some-repo --issue-file issue.md --check "bun test"
# optional: --review-shortlist .claude/review-shortlist.json --review-rubric docs/rubric.md
Fill in TYPESAFE_API_KEY, plus ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN (or neither, to use your local Claude Code login). Bun loads .env.local and .env; both are gitignored.
The issue file's first line is the title (# Title). The rest is the body.