Reusable composite action for label-triggered issue automation: assess (request more info or implement), implement-verify loop, then create PR or iterate on an existing PR after review.
- Workflow — Ensure
.github/workflows/issue-auto-implement.ymlexists and calls this action (see the workflow in this repo for the exacton:anduses:). If implement might change workflow files, see CI/CD for push permission requirements. - Secrets and variables — In the repo: Settings → Secrets and variables → Actions. Add secret
AUTO_IMPLEMENT_ANTHROPIC_API_KEY(Anthropic API key). Optionally addAUTO_IMPLEMENT_GITHUB_PUSH_TOKEN(a PAT withreposcope) so CI checks run on bot-created PRs (see CI checks on bot-created PRs). For who can trigger, set one of:AUTO_IMPLEMENT_ALLOWED_TRIGGER_MIN_PERMISSION(e.g.pushormaintain; works with default token) orAUTO_IMPLEMENT_ALLOWED_TRIGGER_TEAM(e.g.org/team; token needsread:org). - Trigger label — Create the labels once so you can add them to issues. Either run the Issue auto-implement setup workflow (Actions → Issue auto-implement setup → Run workflow), which creates
automation/auto-implement,automation/needs-info, andautomation/pr-created; or create the trigger labelautomation/auto-implementmanually in the repo (Settings or Issues → Labels). The main action also ensures these labels exist when it runs, but the trigger label must exist before you can add it to an issue. - Trigger — On an issue, add the label
automation/auto-implement. The workflow runs: it assesses the issue (request more info vs implement), and if implement, runs the Claude Code CLI and opens a PR. You can also comment on the issue (to add context and re-trigger) or review the PR (to iterate).
By default, PRs created with GITHUB_TOKEN do not trigger pull_request workflows (a GitHub restriction to prevent recursive runs). To get CI checks on bot-created PRs, set the optional push_token input to a PAT or GitHub App installation token. The action uses this token for git push and PR creation, so GitHub sees events from a non-Actions identity and triggers all pull_request workflows normally. Accepted token types:
- Personal Access Token (classic) —
reposcope - Personal Access Token (fine-grained) —
contents: write+pull-requests: writepermissions - GitHub App installation token — same permissions (e.g. via
actions/create-github-app-token)
If push_token is not set, the action falls back to github_token and CI workflows will not trigger automatically on bot PRs.
The workflow is triggered by issues.labeled. When this action adds a label (e.g. automation/needs-info or automation/pr-created), GitHub sends a new issues.labeled event, so another workflow run is started. The job only runs when the label added is automation/auto-implement (see the workflow’s if:), so those extra runs skip the job and do no work. You will see multiple runs per issue; only the runs triggered by the trigger label (or by comment/PR review) actually execute the action. GitHub does not support filtering on: issues.labeled by label name, so this behavior is expected.
Used by .github/workflows/issue-auto-implement.yml. Requires anthropic_api_key (e.g. from repo secret AUTO_IMPLEMENT_ANTHROPIC_API_KEY), one of github_allowed_trigger_min_permission or github_allowed_trigger_team (repo variables), and github_token from the workflow.
| Input | Required | Default | Description |
|---|---|---|---|
anthropic_api_key |
Yes | - | Claude API key. Set via repo secret AUTO_IMPLEMENT_ANTHROPIC_API_KEY so multiple actions can use different keys. |
github_token |
Yes | - | Token (contents, issues, pull-requests; read:org only if using team check) |
context_files |
No | AGENTS.md,REFERENCE.md | Comma-separated paths for assessment context |
assessment_reference_issue |
No | 192 | Reference issue number for "enough information" |
label_prefix |
No | automation | Prefix for labels (e.g. automation/auto-implement) |
verify_commands |
No | go test ./... | Commands run for verification |
max_implement_retries |
No | 3 | Max retries on verify failure (cap 5) |
github_allowed_trigger_team |
No* | - | Team slug (e.g. org/team); only members can trigger. Repo variable AUTO_IMPLEMENT_ALLOWED_TRIGGER_TEAM. Ignored if min_permission is set. Token needs read:org. |
github_allowed_trigger_min_permission |
No* | - | Require actor has at least this repo permission: triage, push, maintain, or admin. Repo variable AUTO_IMPLEMENT_ALLOWED_TRIGGER_MIN_PERMISSION. Works with default GITHUB_TOKEN. |
push_token |
No | - | PAT or GitHub App installation token for git push and PR creation. When set, GitHub triggers pull_request workflows on bot PRs. Falls back to github_token. |
post_pr_comment |
No | false | When true, post a comment on the issue linking to the new PR when one is created. |
*One of github_allowed_trigger_min_permission or github_allowed_trigger_team must be set (via repo variables).
Secrets and variables use an action-specific prefix (e.g. AUTO_IMPLEMENT_) so each action can have its own keys/variables and it's clear which workflow uses which. This also avoids clashing with platform-reserved names (e.g. GITHUB_*).
To use this action in GitHub Actions:
- Workflow — Call the action from a workflow (e.g.
.github/workflows/issue-auto-implement.yml) onissues.labeled,issue_comment,pull_request_review, and/orpull_request_review_comment. The job needscontents: write,issues: write,pull-requests: write. If the implement step may edit files under.github/workflows/, GitHub may reject the push; the workflow syntax has noworkflowspermission key. Enable Settings → Actions → General → Allow GitHub Actions to create and approve pull requests (or use a PAT with appropriate scope) so the run can push workflow file changes. - Secrets — Add
AUTO_IMPLEMENT_ANTHROPIC_API_KEY(repo secret). Used for the assess step and passed to the Claude Code CLI in the implement step. Optionally addAUTO_IMPLEMENT_GITHUB_PUSH_TOKEN(a PAT withreposcope, or fine-grained withcontents: write+pull-requests: write) so CI checks run on bot-created PRs. - Variables (trigger gate) — Set one of:
AUTO_IMPLEMENT_ALLOWED_TRIGGER_MIN_PERMISSION(repo variable):triage,push,maintain, oradmin. Only users with at least this repo permission can trigger. Works with defaultGITHUB_TOKEN.AUTO_IMPLEMENT_ALLOWED_TRIGGER_TEAM(repo variable): org/team slug (e.g.org/team-name). Only team members can trigger. Token must haveread:org(use a PAT ifGITHUB_TOKENlacks it).
- Token — Pass
github_token(e.g.secrets.GITHUB_TOKEN). If using the team check, the token needsread:org; the permission check works with the default token. - Implement in CI — The action installs the Claude Code CLI (
@anthropic-ai/claude-code) when the assess outcome isimplement, so the workflow does not need to install it. Implement runs in the repo with Read/Edit/Bash; the CLI usesAUTO_IMPLEMENT_ANTHROPIC_API_KEY.
No other setup is required. Optionally set verify_commands (default go test ./...) and context_files (default AGENTS.md,REFERENCE.md) to match your repo.
AUTO_IMPLEMENT_ANTHROPIC_API_KEY(repo secret) — Claude API key for the assess and implement steps. Add under Settings → Secrets and variables → Actions.AUTO_IMPLEMENT_GITHUB_PUSH_TOKEN(repo secret, optional) — PAT or GitHub App installation token for git push and PR creation. When set, GitHub triggerspull_requestworkflows on bot PRs so CI checks appear. See CI checks on bot-created PRs for accepted token types.- Trigger gate (set one):
AUTO_IMPLEMENT_ALLOWED_TRIGGER_MIN_PERMISSION(repo variable) — Require the triggering user to have at least this repo permission:triage,push,maintain, oradmin. Works with the defaultGITHUB_TOKEN. Add under Settings → Secrets and variables → Actions → Variables.AUTO_IMPLEMENT_ALLOWED_TRIGGER_TEAM(repo variable) — GitHub Team slug (e.g.org/team-name) whose members may trigger. The first step checksgithub.actoragainst this team. The token needsread:org; ifGITHUB_TOKENlacks it, use a PAT and pass it asgithub_token.
- issues.labeled — prefixed trigger label (e.g.
automation/auto-implement) - issue_comment.created — on an issue with that label (redirect to PR if PR exists)
- pull_request_review.submitted / pull_request_review_comment.created — PR from automation branch or with "Closes #N"
The action ensures these labels exist (creates them if missing): {prefix}/auto-implement, {prefix}/needs-info, {prefix}/pr-created.
When a run fails, open the job log and check the Implement and verify (loop) step:
Error: spawnSync claude ETIMEDOUT— The Claude Code CLI hit the timeout inimplement.ts(default 35 minutes). The runner killed the subprocess before Claude finished. Increase the timeout inassess/src/implement.ts(e.g. to 35–40 min) or simplify the issue scope. The issue comment will say "verification failed" but the real cause is implement timeout.- Other failure right after
npx tsx src/implement.ts— The implement script exited 1. Common causes: Claude Code CLI exited non-zero (error) or missing env (e.g. fetch issue failed). Check stderr for the exact error. - "Verification failed (attempt 1 of N)" and eventually "Verification failed after N attempts" — The verify command (e.g.
go test -short ./...) failed on every attempt. Fix the failing tests or adjustverify_commandsin the workflow.
When the issue is already implemented and Claude correctly writes only .comment_body (no code changes), the loop skips verification and exits success so the run completes and a PR/comment is posted.
From the repo root, run the assess script tests:
cd .github/actions/issue-auto-implement/assess && npm ci && npm testCI runs these in .github/workflows/issue-auto-implement-test.yml when you push or open a PR that touches this action.
Integration tests (Claude API): Tests in assess/test/integration/ call the real Anthropic API. They do not run with npm test. From the assess directory, run npm run test:integration (requires AUTO_IMPLEMENT_ANTHROPIC_API_KEY in .env or env). Unit tests live in assess/test/unit/; shared fixtures in assess/test/fixtures/. You can add integration tests to CI later with the secret configured.
Scripts load a local .env file so you don't have to pass secrets on the command line. They look for .env in (1) the action root (.github/actions/issue-auto-implement/.env) and (2) the current working directory (e.g. assess/.env). Later overrides earlier; shell env still wins.
| Variable | Required for | How to get it |
|---|---|---|
AUTO_IMPLEMENT_ANTHROPIC_API_KEY |
Assess, Implement | Anthropic console → API keys. Assess uses it directly; implement passes it to Claude Code CLI (claude on PATH). |
GITHUB_TOKEN |
Implement; optional for Assess | gh auth token, or a PAT with repo, read:org. |
GITHUB_REPOSITORY |
Implement | owner/repo (e.g. hookdeck/hookdeck-cli). |
ISSUE_NUMBER |
Implement | The issue number to implement. |
GITHUB_EVENT_PATH |
Assess (when not using fixture) | Path to event JSON; for fixture: ./fixtures/issue-labeled.json. |
GITHUB_EVENT_NAME |
Assess | e.g. issues or issue_comment. |
GITHUB_WORKSPACE |
Optional | Repo root; default inferred from cwd when run from assess/. |
CONTEXT_FILES |
Optional | Comma-separated paths (relative to repo root) for Claude context. |
VERIFICATION_NOTES |
Optional (Implement) | Notes from assess step. |
REVIEW_FEEDBACK |
Optional (Implement) | When the run was triggered by a PR review or comment on a PR, the action passes the review/comment text so the implement step can address it (e.g. "add unit and acceptance tests"). |
PREVIOUS_VERIFY_OUTPUT |
Optional (Implement retries) | Previous verify failure output. |
- From the action root:
cp .env.example .env - Edit
.envand set at leastAUTO_IMPLEMENT_ANTHROPIC_API_KEYand (for implement)GITHUB_TOKEN. Optionally run./scripts/setup-local-env.sh --with-ghto fillGITHUB_TOKENfromgh auth token; use--template-onlyto only create.envfrom.env.example.
Uses a fixture as the GitHub event. Claude decides whether to implement or request_info; output is JSON to stdout.
cd .github/actions/issue-auto-implement/assess
npm run assess:fixtureWith .env in place, no need to pass the key on the command line. Optional: set GITHUB_TOKEN and GITHUB_REPOSITORY to exercise redirect-to-PR and fetch-comments. Logging: The script always logs Claude's raw response to stderr (the JSON decision and any surrounding text) and a one-line summary (e.g. Assess: action=implement issue_number=215 review_feedback=52 chars), so CI logs show what was decided and what the model returned. Set ASSESS_DEBUG=1 to also log the full prompt (issue, comments, context files) when debugging. Other fixtures: GITHUB_EVENT_PATH=./test/fixtures/issue-comment.json GITHUB_EVENT_NAME=issue_comment npx tsx src/index.ts.
Fetches the issue from the GitHub API, then runs Claude Code CLI in the repo (claude on PATH with Read/Edit/Bash). The CLI implements the issue in-repo and writes commit/PR meta files. Use a branch you can discard or reset. Requires Claude Code CLI installed and AUTO_IMPLEMENT_ANTHROPIC_API_KEY set (passed to the CLI).
cd .github/actions/issue-auto-implement/assess
npm run implement:issueWith .env set (e.g. ISSUE_NUMBER, GITHUB_REPOSITORY, GITHUB_TOKEN, AUTO_IMPLEMENT_ANTHROPIC_API_KEY), no need to pass them inline. Override any var on the command line if needed (e.g. ISSUE_NUMBER=42 npm run implement:issue). Then from the repo root inspect git status and the commit message at .github/actions/issue-auto-implement/.commit_msg. Optionally set VERIFICATION_NOTES, REVIEW_FEEDBACK (reviewer or PR comment text to address), and CONTEXT_FILES.
For implementation details and verification steps, see AGENTS.md.
To test the full flow locally against a real GitHub issue and create a PR, use the local assess script (fetches the issue from the API and runs the same assess logic). With APPLY=1 the script applies the outcome: posts the request-for-more-info or redirect comment on the issue, or runs implement and push (creates/updates the PR). When the outcome is implement, the script creates or reuses a worktree at .worktrees/auto-implement-issue-<N> so your current branch is left untouched; implement runs there, then commit/push/PR is done in TypeScript (assess/src/push-and-open-pr.ts). The workflow does not need to run; you trigger each step locally and optionally pass COMMENT_BODY (after you add a comment on the issue) or REVIEW_BODY (after you review the PR).