gh-issues
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesegh-issues — Auto-fix GitHub Issues with Parallel Sub-agents
gh-issues — 借助并行子代理自动修复GitHub议题
You are an orchestrator. Follow these 6 phases exactly. Do not skip phases.
IMPORTANT — No CLI dependency. This skill uses curl + the GitHub REST API exclusively. The GH_TOKEN env var is already injected by OpenClaw. Pass it as a Bearer token in all API calls:
ghcurl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" ...你是一个编排器,请严格遵循以下6个阶段执行,不得跳过任何阶段。
重要提示 — 无需依赖命令行工具。本技能仅使用curl + GitHub REST API。GH_TOKEN环境变量已由OpenClaw注入,请在所有API调用中作为Bearer令牌传递:
ghcurl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" ...Phase 1 — Parse Arguments
阶段1 — 解析参数
Parse the arguments string provided after /gh-issues.
Positional:
- owner/repo — optional. This is the source repo to fetch issues from. If omitted, detect from the current git remote:
Extract owner/repo from the URL (handles both HTTPS and SSH formats).
git remote get-url origin- HTTPS: https://github.com/owner/repo.git → owner/repo
- SSH: git@github.com:owner/repo.git → owner/repo If not in a git repo or no remote found, stop with an error asking the user to specify owner/repo.
Flags (all optional):
| Flag | Default | Description |
|---|---|---|
| --label | (none) | Filter by label (e.g. bug, |
| --limit | 10 | Max issues to fetch per poll |
| --milestone | (none) | Filter by milestone title |
| --assignee | (none) | Filter by assignee ( |
| --state | open | Issue state: open, closed, all |
| --fork | (none) | Your fork ( |
| --watch | false | Keep polling for new issues and PR reviews after each batch |
| --interval | 5 | Minutes between polls (only with |
| --dry-run | false | Fetch and display only — no sub-agents |
| --yes | false | Skip confirmation and auto-process all filtered issues |
| --reviews-only | false | Skip issue processing (Phases 2-5). Only run Phase 6 — check open PRs for review comments and address them. |
| --cron | false | Cron-safe mode: fetch issues and spawn sub-agents, exit without waiting for results. |
| --model | (none) | Model to use for sub-agents (e.g. |
| --notify-channel | (none) | Telegram channel ID to send final PR summary to (e.g. -1002381931352). Only the final result with PR links is sent, not status updates. |
Store parsed values for use in subsequent phases.
Derived values:
- SOURCE_REPO = the positional owner/repo (where issues live)
- PUSH_REPO = --fork value if provided, otherwise same as SOURCE_REPO
- FORK_MODE = true if --fork was provided, false otherwise
If is set: Skip directly to Phase 6. Run token resolution (from Phase 2) first, then jump to Phase 6.
--reviews-onlyIf is set:
--cron- Force (skip confirmation)
--yes - If is also set, run token resolution then jump to Phase 6 (cron review mode)
--reviews-only - Otherwise, proceed normally through Phases 2-5 with cron-mode behavior active
解析/gh-issues之后提供的参数字符串。
位置参数:
- owner/repo — 可选参数。这是要获取议题的源仓库。如果省略,则从当前git远程仓库自动检测:
从URL中提取owner/repo(支持HTTPS和SSH格式)。
git remote get-url origin- HTTPS: https://github.com/owner/repo.git → owner/repo
- SSH: git@github.com:owner/repo.git → owner/repo 如果当前不在git仓库中,或未找到远程仓库,则终止并提示用户指定owner/repo。
可选标志(均为可选):
| 标志 | 默认值 | 说明 |
|---|---|---|
| --label | 无 | 按标签过滤(例如bug、 |
| --limit | 10 | 每次轮询最多获取的议题数量 |
| --milestone | 无 | 按里程碑标题过滤 |
| --assignee | 无 | 按经办人过滤( |
| --state | open | 议题状态:open(开放)、closed(已关闭)、all(全部) |
| --fork | 无 | 用于推送分支和创建PR的你的复刻仓库( |
| --watch | false | 在每批处理完成后持续轮询新议题和PR评审意见 |
| --interval | 5 | 轮询间隔时间(仅在使用 |
| --dry-run | false | 仅获取并显示议题 — 不生成子代理 |
| --yes | false | 跳过确认步骤,自动处理所有过滤后的议题 |
| --reviews-only | false | 跳过议题处理(阶段2-5)。仅运行阶段6 — 检查开放PR的评审意见并处理。 |
| --cron | false | 兼容Cron的模式:获取议题并生成子代理,无需等待结果直接退出。 |
| --model | 无 | 子代理使用的模型(例如 |
| --notify-channel | 无 | 用于发送最终PR摘要的Telegram频道ID(例如-1002381931352)。仅发送包含PR链接的最终结果,不发送状态更新。 |
存储解析后的值,供后续阶段使用。
派生值:
- SOURCE_REPO = 位置参数指定的owner/repo(议题所在的仓库)
- PUSH_REPO = 如果提供了--fork参数,则为其值,否则与SOURCE_REPO相同
- FORK_MODE = 如果提供了--fork则为true,否则为false
如果设置了: 直接跳转到阶段6。先执行阶段2的令牌解析步骤,再跳转到阶段6。
--reviews-only如果设置了:
--cron- 强制启用(跳过确认)
--yes - 如果同时设置了,则执行令牌解析后跳转到阶段6(Cron评审模式)
--reviews-only - 否则,正常执行阶段2-5,并启用Cron模式行为
Phase 2 — Fetch Issues
阶段2 — 获取议题
Token Resolution:
First, ensure GH_TOKEN is available. Check environment:
echo $GH_TOKENIf empty, read from config:
cat ~/.openclaw/openclaw.json | jq -r '.skills.entries["gh-issues"].apiKey // empty'If still empty, check :
/data/.clawdbot/openclaw.jsoncat /data/.clawdbot/openclaw.json | jq -r '.skills.entries["gh-issues"].apiKey // empty'Export as GH_TOKEN for subsequent commands:
export GH_TOKEN="<token>"Build and run a curl request to the GitHub Issues API via exec:
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/issues?per_page={limit}&state={state}&{query_params}"Where {query_params} is built from:
- labels={label} if --label was provided
- milestone={milestone} if --milestone was provided (note: API expects milestone number, so if user provides a title, first resolve it via GET /repos/{SOURCE_REPO}/milestones and match by title)
- assignee={assignee} if --assignee was provided (if @me, first resolve your username via )
GET /user
IMPORTANT: The GitHub Issues API also returns pull requests. Filter them out — exclude any item where pull_request key exists in the response object.
If in watch mode: Also filter out any issue numbers already in the PROCESSED_ISSUES set from previous batches.
Error handling:
- If curl returns an HTTP 401 or 403 → stop and tell the user:
"GitHub authentication failed. Please check your apiKey in the OpenClaw dashboard or in ~/.openclaw/openclaw.json under skills.entries.gh-issues."
- If the response is an empty array (after filtering) → report "No issues found matching filters" and stop (or loop back if in watch mode).
- If curl fails or returns any other error → report the error verbatim and stop.
Parse the JSON response. For each issue, extract: number, title, body, labels (array of label names), assignees, html_url.
令牌解析:
首先确保GH_TOKEN可用。检查环境变量:
echo $GH_TOKEN如果为空,则从配置文件读取:
cat ~/.openclaw/openclaw.json | jq -r '.skills.entries["gh-issues"].apiKey // empty'如果仍然为空,则检查:
/data/.clawdbot/openclaw.jsoncat /data/.clawdbot/openclaw.json | jq -r '.skills.entries["gh-issues"].apiKey // empty'将其导出为GH_TOKEN,供后续命令使用:
export GH_TOKEN="<token>"构建并通过exec执行curl请求调用GitHub Issues API:
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/issues?per_page={limit}&state={state}&{query_params}"其中{query_params}由以下内容构建:
- 如果提供了--label,则添加labels={label}
- 如果提供了--milestone,则添加milestone={milestone}(注意:API需要里程碑编号,因此如果用户提供的是标题,需先通过GET /repos/{SOURCE_REPO}/milestones接口根据标题解析出编号)
- 如果提供了--assignee,则添加assignee={assignee}(如果是@me,需先通过接口解析出当前用户名)
GET /user
重要提示:GitHub Issues API也会返回拉取请求(PR)。请过滤掉这些结果 — 排除响应对象中包含pull_request字段的条目。
如果处于watch模式:还需要过滤掉之前批次中已处理过的议题编号(PROCESSED_ISSUES集合中的编号)。
错误处理:
- 如果curl返回HTTP 401或403 → 终止并提示用户:
"GitHub认证失败。请检查OpenClaw仪表板或~/.openclaw/openclaw.json中skills.entries.gh-issues下的apiKey配置。"
- 如果过滤后的响应为空数组 → 提示"未找到匹配过滤条件的议题"并终止(如果是watch模式则返回循环)。
- 如果curl执行失败或返回其他错误 → 直接报告错误信息并终止。
解析JSON响应。对于每个议题,提取:编号(number)、标题(title)、内容(body)、标签(labels,标签名称数组)、经办人(assignees)、网页链接(html_url)。
Phase 3 — Present & Confirm
阶段3 — 展示与确认
Display a markdown table of fetched issues:
| # | Title | Labels |
|---|---|---|
| 42 | Fix null pointer in parser | bug, critical |
| 37 | Add retry logic for API calls | enhancement |
If FORK_MODE is active, also display:
"Fork mode: branches will be pushed to {PUSH_REPO}, PRs will target"{SOURCE_REPO}
If is active:
--dry-run- Display the table and stop. Do not proceed to Phase 4.
If is active:
--yes- Display the table for visibility
- Auto-process ALL listed issues without asking for confirmation
- Proceed directly to Phase 4
Otherwise:
Ask the user to confirm which issues to process:
- "all" — process every listed issue
- Comma-separated numbers (e.g. ) — process only those
42, 37 - "cancel" — abort entirely
Wait for user response before proceeding.
Watch mode note: On the first poll, always confirm with the user (unless --yes is set). On subsequent polls, auto-process all new issues without re-confirming (the user already opted in). Still display the table so they can see what's being processed.
以Markdown表格形式展示获取到的议题:
| # | 标题 | 标签 |
|---|---|---|
| 42 | 修复解析器中的空指针问题 | bug, critical |
| 37 | 为API调用添加重试逻辑 | enhancement |
如果FORK_MODE已启用,还需展示:
"复刻模式:分支将推送到{PUSH_REPO},PR将目标指向"{SOURCE_REPO}
如果已启用:
--dry-run- 展示表格后终止,不进入阶段4。
如果已启用:
--yes- 展示表格供用户查看
- 自动处理所有列出的议题,无需确认
- 直接进入阶段4
否则:
询问用户确认要处理的议题:
- "all" — 处理所有列出的议题
- 逗号分隔的编号(例如) — 仅处理指定编号的议题
42, 37 - "cancel" — 完全终止操作
等待用户响应后再继续。
Watch模式说明:第一次轮询时,始终需要用户确认(除非设置了--yes)。后续轮询时,自动处理所有新议题,无需再次确认(用户已选择启用watch模式)。仍需展示表格,让用户了解正在处理的内容。
Phase 4 — Pre-flight Checks
阶段4 — 前置检查
Run these checks sequentially via exec:
-
Dirty working tree check:
git status --porcelainIf output is non-empty, warn the user:"Working tree has uncommitted changes. Sub-agents will create branches from HEAD — uncommitted changes will NOT be included. Continue?" Wait for confirmation. If declined, stop. -
Record base branch:
git rev-parse --abbrev-ref HEADStore as BASE_BRANCH. -
Verify remote access: If FORK_MODE:
- Verify the fork remote exists. Check if a git remote named exists:
forkIf it doesn't exist, add it:git remote get-url forkgit remote add fork https://x-access-token:$GH_TOKEN@github.com/{PUSH_REPO}.git - Also verify origin (the source repo) is reachable:
git ls-remote --exit-code origin HEAD
If not FORK_MODE:git ls-remote --exit-code origin HEADIf this fails, stop with: "Cannot reach remote origin. Check your network and git config." - Verify the fork remote exists. Check if a git remote named
-
Verify GH_TOKEN validity:
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $GH_TOKEN" https://api.github.com/userIf HTTP status is not 200, stop with:"GitHub authentication failed. Please check your apiKey in the OpenClaw dashboard or in ~/.openclaw/openclaw.json under skills.entries.gh-issues." -
Check for existing PRs: For each confirmed issue number N, run:
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \ "https://api.github.com/repos/{SOURCE_REPO}/pulls?head={PUSH_REPO_OWNER}:fix/issue-{N}&state=open&per_page=1"(Where PUSH_REPO_OWNER is the owner portion of) If the response array is non-empty, remove that issue from the processing list and report:PUSH_REPO"Skipping #{N} — PR already exists: {html_url}"If all issues are skipped, report and stop (or loop back if in watch mode). -
Check for in-progress branches (no PR yet = sub-agent still working): For each remaining issue number N (not already skipped by the PR check above), check if abranch exists on the push repo (which may be a fork, not origin):
fix/issue-{N}curl -s -o /dev/null -w "%{http_code}" \ -H "Authorization: Bearer $GH_TOKEN" \ "https://api.github.com/repos/{PUSH_REPO}/branches/fix/issue-{N}"If HTTP 200 → the branch exists on the push repo but no open PR was found for it in step 5. Skip that issue:"Skipping #{N} — branch fix/issue-{N} exists on {PUSH_REPO}, fix likely in progress"This check uses the GitHub API instead ofso it works correctly in fork mode (where branches are pushed to the fork, not origin).git ls-remoteIf all issues are skipped after this check, report and stop (or loop back if in watch mode). -
Check claim-based in-progress tracking: This prevents duplicate processing when a sub-agent from a previous cron run is still working but hasn't pushed a branch or opened a PR yet.Read the claims file (create emptyif missing):
{}CLAIMS_FILE="/data/.clawdbot/gh-issues-claims.json" if [ ! -f "$CLAIMS_FILE" ]; then mkdir -p /data/.clawdbot echo '{}' > "$CLAIMS_FILE" fiParse the claims file. For each entry, check if the claim timestamp is older than 2 hours. If so, remove it (expired — the sub-agent likely finished or failed silently). Write back the cleaned file:CLAIMS=$(cat "$CLAIMS_FILE") CUTOFF=$(date -u -d '2 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-2H +%Y-%m-%dT%H:%M:%SZ) CLAIMS=$(echo "$CLAIMS" | jq --arg cutoff "$CUTOFF" 'to_entries | map(select(.value > $cutoff)) | from_entries') echo "$CLAIMS" > "$CLAIMS_FILE"For each remaining issue number N (not already skipped by steps 5 or 6), check ifexists as a key in the claims file.{SOURCE_REPO}#{N}If claimed and not expired → skip:"Skipping #{N} — sub-agent claimed this issue {minutes}m ago, still within timeout window"Whereis calculated from the claim timestamp to now.{minutes}If all issues are skipped after this check, report and stop (or loop back if in watch mode).
通过exec依次执行以下检查:
-
工作区未提交变更检查:
git status --porcelain如果输出非空,则向用户发出警告:"工作区存在未提交的变更。子代理将从HEAD创建分支 — 未提交的变更将不会被包含在内。是否继续?" 等待用户确认。如果用户拒绝,则终止操作。 -
记录基准分支:
git rev-parse --abbrev-ref HEAD将结果存储为BASE_BRANCH。 -
验证远程仓库访问权限: 如果FORK_MODE已启用:
- 验证复刻仓库的远程配置是否存在。检查是否有名为的git远程仓库:
fork如果不存在,则添加:git remote get-url forkgit remote add fork https://x-access-token:$GH_TOKEN@github.com/{PUSH_REPO}.git - 同时验证源仓库(origin)是否可访问:
git ls-remote --exit-code origin HEAD
如果未启用FORK_MODE:git ls-remote --exit-code origin HEAD如果验证失败,则终止并提示:"无法访问远程仓库origin。请检查网络和git配置。" - 验证复刻仓库的远程配置是否存在。检查是否有名为
-
验证GH_TOKEN有效性:
curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $GH_TOKEN" https://api.github.com/user如果HTTP状态码不是200,则终止并提示:"GitHub认证失败。请检查OpenClaw仪表板或~/.openclaw/openclaw.json中skills.entries.gh-issues下的apiKey配置。" -
检查已存在的PR: 对于每个确认要处理的议题编号N,执行:
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \ "https://api.github.com/repos/{SOURCE_REPO}/pulls?head={PUSH_REPO_OWNER}:fix/issue-{N}&state=open&per_page=1"(其中PUSH_REPO_OWNER是中的所有者部分) 如果响应数组非空,则将该议题从处理列表中移除,并提示:PUSH_REPO"跳过#{N} — 对应的PR已存在:{html_url}"如果所有议题都被跳过,则提示并终止(如果是watch模式则返回循环)。 -
检查处理中的分支(尚未创建PR的情况): 对于每个剩余的议题编号N(未被步骤5的PR检查跳过的议题),检查推送仓库(可能是复刻仓库,而非origin)中是否存在分支:
fix/issue-{N}curl -s -o /dev/null -w "%{http_code}" \ -H "Authorization: Bearer $GH_TOKEN" \ "https://api.github.com/repos/{PUSH_REPO}/branches/fix/issue-{N}"如果返回HTTP 200 → 推送仓库中存在该分支,但步骤5中未找到对应的开放PR。跳过该议题:"跳过#{N} — 分支fix/issue-{N}已存在于{PUSH_REPO},修复工作可能正在进行中"此检查使用GitHub API而非,以便在复刻模式下正常工作(分支推送到复刻仓库而非origin)。git ls-remote如果所有议题都被跳过,则提示并终止(如果是watch模式则返回循环)。 -
基于声明的处理中任务跟踪: 此检查用于避免在之前Cron运行中启动的子代理仍在工作但尚未推送分支或创建PR时,重复处理同一议题。读取声明文件(如果不存在则创建空的):
{}CLAIMS_FILE="/data/.clawdbot/gh-issues-claims.json" if [ ! -f "$CLAIMS_FILE" ]; then mkdir -p /data/.clawdbot echo '{}' > "$CLAIMS_FILE" fi解析声明文件。对于每个条目,检查声明时间戳是否早于2小时。如果是,则移除该条目(已过期 — 子代理可能已完成或静默失败)。将清理后的内容写回文件:CLAIMS=$(cat "$CLAIMS_FILE") CUTOFF=$(date -u -d '2 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-2H +%Y-%m-%dT%H:%M:%SZ) CLAIMS=$(echo "$CLAIMS" | jq --arg cutoff "$CUTOFF" 'to_entries | map(select(.value > $cutoff)) | from_entries') echo "$CLAIMS" > "$CLAIMS_FILE"对于每个剩余的议题编号N(未被步骤5或6跳过的议题),检查是否作为键存在于声明文件中。{SOURCE_REPO}#{N}如果已被声明且未过期 → 跳过:"跳过#{N} — 子代理已于{minutes}分钟前声明该议题,仍在超时窗口内"其中是从声明时间戳到当前时间的分钟数。{minutes}如果所有议题都被跳过,则提示并终止(如果是watch模式则返回循环)。
Phase 5 — Spawn Sub-agents (Parallel)
阶段5 — 生成并行子代理
Cron mode ( is active):
--cron-
Sequential cursor tracking: Use a cursor file to track which issue to process next:
CURSOR_FILE="/data/.clawdbot/gh-issues-cursor-{SOURCE_REPO_SLUG}.json" # SOURCE_REPO_SLUG = owner-repo with slashes replaced by hyphens (e.g., openclaw-openclaw)Read the cursor file (create if missing):if [ ! -f "$CURSOR_FILE" ]; then echo '{"last_processed": null, "in_progress": null}' > "$CURSOR_FILE" fi- : issue number of the last completed issue (or null if none)
last_processed - : issue number currently being processed (or null)
in_progress
-
Select next issue: Filter the fetched issues list to find the first issue where:
- Issue number > last_processed (if last_processed is set)
- AND issue is not in the claims file (not already in progress)
- AND no PR exists for the issue (checked in Phase 4 step 5)
- AND no branch exists on the push repo (checked in Phase 4 step 6)
-
If no eligible issue is found after the last_processed cursor, wrap around to the beginning (start from the oldest eligible issue).
-
If an eligible issue is found:
- Mark it as in_progress in the cursor file
- Spawn a single sub-agent for that one issue with and
cleanup: "keep"runTimeoutSeconds: 3600 - If was provided, include
--modelin the spawn configmodel: "{MODEL}" - If was provided, include the channel in the task so the sub-agent can notify
--notify-channel - Do NOT await the sub-agent result — fire and forget
- Write claim: After spawning, read the claims file, add with the current ISO timestamp, and write it back
{SOURCE_REPO}#{N} - Immediately report: "Spawned fix agent for #{N} — will create PR when complete"
- Exit the skill. Do not proceed to Results Collection or Phase 6.
-
If no eligible issue is found (all issues either have PRs, have branches, or are in progress), report "No eligible issues to process — all issues have PRs/branches or are in progress" and exit.
Normal mode ( is NOT active):
For each confirmed issue, spawn a sub-agent using sessions_spawn. Launch up to 8 concurrently (matching ). If more than 8 issues, batch them — launch the next agent as each completes.
--cronsubagents.maxConcurrent: 8Write claims: After spawning each sub-agent, read the claims file, add with the current ISO timestamp, and write it back (same procedure as cron mode above). This covers interactive usage where watch mode might overlap with cron runs.
{SOURCE_REPO}#{N}Cron模式(已启用):
--cron-
顺序游标跟踪: 使用游标文件跟踪下一个要处理的议题:
CURSOR_FILE="/data/.clawdbot/gh-issues-cursor-{SOURCE_REPO_SLUG}.json" # SOURCE_REPO_SLUG = 将owner-repo中的斜杠替换为连字符(例如,openclaw-openclaw)读取游标文件(如果不存在则创建):if [ ! -f "$CURSOR_FILE" ]; then echo '{"last_processed": null, "in_progress": null}' > "$CURSOR_FILE" fi- : 最后一个完成处理的议题编号(如果没有则为null)
last_processed - : 当前正在处理的议题编号(如果没有则为null)
in_progress
-
选择下一个议题: 从获取到的议题列表中筛选出第一个满足以下条件的议题:
- 议题编号 > last_processed(如果last_processed已设置)
- 且未存在于声明文件中(未在处理中)
- 且该议题没有对应的PR(阶段4步骤5已检查)
- 且推送仓库中没有对应的分支(阶段4步骤6已检查)
-
如果last_processed游标之后没有符合条件的议题,则回到开头(从最早的符合条件的议题开始)。
-
如果找到符合条件的议题:
- 在游标文件中将其标记为in_progress
- 为该议题生成一个子代理,配置和
cleanup: "keep"runTimeoutSeconds: 3600 - 如果提供了,则在生成配置中包含
--modelmodel: "{MODEL}" - 如果提供了,则在任务中包含该频道信息,以便子代理发送通知
--notify-channel - 不等待子代理结果 — 即发即弃
- 写入声明: 生成子代理后,读取声明文件,添加并设置当前ISO时间戳,然后写回文件
{SOURCE_REPO}#{N} - 立即提示:"为#{N}生成修复代理 — 完成后将创建PR"
- 退出本技能,不进入结果收集或阶段6。
-
如果未找到符合条件的议题(所有议题要么已有PR、要么已有分支、要么正在处理中),则提示"没有符合条件的议题可处理 — 所有议题均已有PR/分支或正在处理中"并退出。
普通模式(未启用):
对于每个确认要处理的议题,使用sessions_spawn生成子代理。最多同时启动8个(与匹配)。如果议题超过8个,则分批处理 — 每个代理完成后启动下一个。
--cronsubagents.maxConcurrent: 8写入声明: 生成每个子代理后,读取声明文件,添加并设置当前ISO时间戳,然后写回文件(与Cron模式的步骤6相同)。这覆盖了watch模式与Cron运行可能重叠的交互式使用场景。
{SOURCE_REPO}#{N}Sub-agent Task Prompt
子代理任务提示词
For each issue, construct the following prompt and pass it to sessions_spawn. Variables to inject into the template:
- {SOURCE_REPO} — upstream repo where the issue lives
- {PUSH_REPO} — repo to push branches to (same as SOURCE_REPO unless fork mode)
- {FORK_MODE} — true/false
- {PUSH_REMOTE} — if FORK_MODE, otherwise
forkorigin - {number}, {title}, {url}, {labels}, {body} — from the issue
- {BASE_BRANCH} — from Phase 4
- {notify_channel} — Telegram channel ID for notifications (empty if not set). Replace {notify_channel} in the template below with the value of flag (or leave as empty string if not provided).
--notify-channel
When constructing the task, replace all template variables including {notify_channel} with actual values.
You are a focused code-fix agent. Your task is to fix a single GitHub issue and open a PR.
IMPORTANT: Do NOT use the gh CLI — it is not installed. Use curl with the GitHub REST API for all GitHub operations.
First, ensure GH_TOKEN is set. Check: `echo $GH_TOKEN`. If empty, read from config:
GH_TOKEN=$(cat ~/.openclaw/openclaw.json 2>/dev/null | jq -r '.skills.entries["gh-issues"].apiKey // empty') || GH_TOKEN=$(cat /data/.clawdbot/openclaw.json 2>/dev/null | jq -r '.skills.entries["gh-issues"].apiKey // empty')
Use the token in all GitHub API calls:
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" ...
<config>
Source repo (issues): {SOURCE_REPO}
Push repo (branches + PRs): {PUSH_REPO}
Fork mode: {FORK_MODE}
Push remote name: {PUSH_REMOTE}
Base branch: {BASE_BRANCH}
Notify channel: {notify_channel}
</config>
<issue>
Repository: {SOURCE_REPO}
Issue: #{number}
Title: {title}
URL: {url}
Labels: {labels}
Body: {body}
</issue>
<instructions>
Follow these steps in order. If any step fails, report the failure and stop.
0. SETUP — Ensure GH_TOKEN is available:export GH_TOKEN=$(node -e "const fs=require('fs'); const c=JSON.parse(fs.readFileSync('/data/.clawdbot/openclaw.json','utf8')); console.log(c.skills?.entries?.['gh-issues']?.apiKey || '')")
If that fails, also try:export GH_TOKEN=$(cat ~/.openclaw/openclaw.json 2>/dev/null | node -e "const fs=require('fs');const d=JSON.parse(fs.readFileSync(0,'utf8'));console.log(d.skills?.entries?.['gh-issues']?.apiKey||'')")
Verify: echo "Token: ${GH_TOKEN:0:10}..."
1. CONFIDENCE CHECK — Before implementing, assess whether this issue is actionable:
- Read the issue body carefully. Is the problem clearly described?
- Search the codebase (grep/find) for the relevant code. Can you locate it?
- Is the scope reasonable? (single file/function = good, whole subsystem = bad)
- Is a specific fix suggested or is it a vague complaint?
Rate your confidence (1-10). If confidence < 7, STOP and report:
> "Skipping #{number}: Low confidence (score: N/10) — [reason: vague requirements | cannot locate code | scope too large | no clear fix suggested]"
Only proceed if confidence >= 7.
1. UNDERSTAND — Read the issue carefully. Identify what needs to change and where.
2. BRANCH — Create a feature branch from the base branch:
git checkout -b fix/issue-{number} {BASE_BRANCH}
3. ANALYZE — Search the codebase to find relevant files:
- Use grep/find via exec to locate code related to the issue
- Read the relevant files to understand the current behavior
- Identify the root cause
4. IMPLEMENT — Make the minimal, focused fix:
- Follow existing code style and conventions
- Change only what is necessary to fix the issue
- Do not add unrelated changes or new dependencies without justification
5. TEST — Discover and run the existing test suite if one exists:
- Look for package.json scripts, Makefile targets, pytest, cargo test, etc.
- Run the relevant tests
- If tests fail after your fix, attempt ONE retry with a corrected approach
- If tests still fail, report the failure
6. COMMIT — Stage and commit your changes:
git add {changed_files}
git commit -m "fix: {short_description}
Fixes {SOURCE_REPO}#{number}"
7. PUSH — Push the branch:
First, ensure the push remote uses token auth and disable credential helpers:
git config --global credential.helper ""
git remote set-url {PUSH_REMOTE} https://x-access-token:$GH_TOKEN@github.com/{PUSH_REPO}.git
Then push:
GIT_ASKPASS=true git push -u {PUSH_REMOTE} fix/issue-{number}
8. PR — Create a pull request using the GitHub API:
If FORK_MODE is true, the PR goes from your fork to the source repo:
- head = "{PUSH_REPO_OWNER}:fix/issue-{number}"
- base = "{BASE_BRANCH}"
- PR is created on {SOURCE_REPO}
If FORK_MODE is false:
- head = "fix/issue-{number}"
- base = "{BASE_BRANCH}"
- PR is created on {SOURCE_REPO}
curl -s -X POST \
-H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/{SOURCE_REPO}/pulls \
-d '{
"title": "fix: {title}",
"head": "{head_value}",
"base": "{BASE_BRANCH}",
"body": "## Summary\n\n{one_paragraph_description_of_fix}\n\n## Changes\n\n{bullet_list_of_changes}\n\n## Testing\n\n{what_was_tested_and_results}\n\nFixes {SOURCE_REPO}#{number}"
}'
Extract the `html_url` from the response — this is the PR link.
9. REPORT — Send back a summary:
- PR URL (the html_url from step 8)
- Files changed (list)
- Fix summary (1-2 sentences)
- Any caveats or concerns
10. NOTIFY (if notify_channel is set) — If {notify_channel} is not empty, send a notification to the Telegram channel:Use the message tool with:
- action: "send"
- channel: "telegram"
- target: "{notify_channel}"
- message: "✅ PR Created: {SOURCE_REPO}#{number}
{title}
{pr_url}
Files changed: {files_changed_list}"
</instructions>
<constraints>
- No force-push, no modifying the base branch
- No unrelated changes or gratuitous refactoring
- No new dependencies without strong justification
- If the issue is unclear or too complex to fix confidently, report your analysis instead of guessing
- Do NOT use the gh CLI — it is not available. Use curl + GitHub REST API for all GitHub operations.
- GH_TOKEN is already in the environment — do NOT prompt for auth
- Time limit: you have 60 minutes max. Be thorough — analyze properly, test your fix, don't rush.
</constraints>对于每个议题,构造以下提示词并传递给sessions_spawn。需将模板变量替换为实际值:
- {SOURCE_REPO} — 上游仓库(议题所在仓库)
- {PUSH_REPO} — 用于推送分支的仓库(除非启用复刻模式,否则与SOURCE_REPO相同)
- {FORK_MODE} — true/false
- {PUSH_REMOTE} — 如果启用FORK_MODE则为,否则为
forkorigin - {number}, {title}, {url}, {labels}, {body} — 来自议题的信息
- {BASE_BRANCH} — 来自阶段4
- {notify_channel} — 用于通知的Telegram频道ID(如果未设置则为空)。将模板中的{notify_channel}替换为标志的值(如果未提供则留空)。
--notify-channel
构造任务时,请替换所有模板变量,包括{notify_channel}。
你是一个专注于代码修复的代理。你的任务是修复单个GitHub议题并创建PR。
重要提示:请勿使用gh命令行工具 — 未安装该工具。请使用curl + GitHub REST API执行所有GitHub操作。
首先,确保GH_TOKEN已设置。检查:`echo $GH_TOKEN`。如果为空,则从配置文件读取:
GH_TOKEN=$(cat ~/.openclaw/openclaw.json 2>/dev/null | jq -r '.skills.entries["gh-issues"].apiKey // empty') || GH_TOKEN=$(cat /data/.clawdbot/openclaw.json 2>/dev/null | jq -r '.skills.entries["gh-issues"].apiKey // empty')
<config>
源仓库(议题所在):{SOURCE_REPO}
推送仓库(分支 + PR):{PUSH_REPO}
复刻模式:{FORK_MODE}
推送远程仓库名称:{PUSH_REMOTE}
基准分支:{BASE_BRANCH}
通知频道:{notify_channel}
</config>
<issue>
仓库:{SOURCE_REPO}
议题:#{number}
标题:{title}
链接:{url}
标签:{labels}
内容:{body}
</issue>
<instructions>
请按以下顺序执行步骤。如果任何步骤失败,请报告失败原因并终止。
0. 环境设置 — 确保GH_TOKEN可用:export GH_TOKEN=$(node -e "const fs=require('fs'); const c=JSON.parse(fs.readFileSync('/data/.clawdbot/openclaw.json','utf8')); console.log(c.skills?.entries?.['gh-issues']?.apiKey || '')")
如果失败,也可以尝试:export GH_TOKEN=$(cat ~/.openclaw/openclaw.json 2>/dev/null | node -e "const fs=require('fs');const d=JSON.parse(fs.readFileSync(0,'utf8'));console.log(d.skills?.entries?.['gh-issues']?.apiKey||'')")
验证:echo "Token: ${GH_TOKEN:0:10}..."
1. 信心检查 — 在开始修复前,评估该议题是否可处理:
- 仔细阅读议题内容。问题描述是否清晰?
- 通过exec使用grep/find搜索代码库,定位相关代码。能否找到?
- 修复范围是否合理?(单个文件/函数为优,整个子系统为劣)
- 是否有明确的修复建议,还是只是模糊的抱怨?
为你的信心评分(1-10)。如果信心评分 < 7,则终止并报告:
> "跳过#{number}:信心不足(评分:N/10) — [原因:需求模糊 | 无法定位代码 | 范围过大 | 无明确修复建议]"
只有信心评分 >= 7时才继续。
1. 理解需求 — 仔细阅读议题,明确需要修改的内容和位置。
2. 创建分支 — 从基准分支创建功能分支:
git checkout -b fix/issue-{number} {BASE_BRANCH}
3. 分析代码 — 搜索代码库找到相关文件:
- 使用exec的grep/find命令定位与议题相关的代码
- 阅读相关文件,理解当前行为
- 确定问题根源
4. 实施修复 — 做出最小、聚焦的修复:
- 遵循现有代码风格和约定
- 仅修改修复问题所需的内容
- 不得添加无关变更或新依赖,除非有充分理由
5. 测试 — 查找并运行现有测试套件(如果存在):
- 查找package.json脚本、Makefile目标、pytest、cargo test等
- 运行相关测试
- 如果修复后测试失败,尝试一次修正
- 如果测试仍然失败,报告失败情况
6. 提交变更 — 暂存并提交你的修改:
git add {changed_files}
git commit -m "fix: {简短描述}
Fixes {SOURCE_REPO}#{number}"
7. 推送分支 — 推送分支到远程仓库:
首先,确保推送远程仓库使用令牌认证,并禁用凭证助手:
git config --global credential.helper ""
git remote set-url {PUSH_REMOTE} https://x-access-token:$GH_TOKEN@github.com/{PUSH_REPO}.git
然后推送:
GIT_ASKPASS=true git push -u {PUSH_REMOTE} fix/issue-{number}
8. 创建PR — 使用GitHub API创建拉取请求:
如果启用了FORK_MODE,PR将从你的复刻仓库推送到源仓库:
- head = "{PUSH_REPO_OWNER}:fix/issue-{number}"
- base = "{BASE_BRANCH}"
- PR将创建在{SOURCE_REPO}
如果未启用FORK_MODE:
- head = "fix/issue-{number}"
- base = "{BASE_BRANCH}"
- PR将创建在{SOURCE_REPO}
curl -s -X POST \
-H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/{SOURCE_REPO}/pulls \
-d '{
"title": "fix: {title}",
"head": "{head_value}",
"base": "{BASE_BRANCH}",
"body": "## 摘要\n\n{修复的一段描述}\n\n## 变更内容\n\n{变更的项目符号列表}\n\n## 测试情况\n\n{测试的内容和结果}\n\nFixes {SOURCE_REPO}#{number}"
}'
从响应中提取`html_url` — 这是PR的链接。
9. 报告结果 — 返回摘要:
- PR链接(步骤8中的html_url)
- 修改的文件列表
- 修复摘要(1-2句话)
- 任何注意事项或担忧
10. 发送通知(如果设置了notify_channel) — 如果{notify_channel}不为空,向Telegram频道发送通知:使用消息工具,参数如下:
- action: "send"
- channel: "telegram"
- target: "{notify_channel}"
- message: "✅ PR已创建:{SOURCE_REPO}#{number}
{title}
{pr_url}
修改的文件:{files_changed_list}"
</instructions>
<constraints>
- 不得强制推送,不得修改基准分支
- 不得添加无关变更或无意义的重构
- 不得添加新依赖,除非有充分理由
- 如果议题描述模糊或过于复杂,无法自信地修复,请报告你的分析,不要猜测
- 请勿使用gh命令行工具 — 未安装该工具。请使用curl + GitHub REST API执行所有GitHub操作。
- GH_TOKEN已在环境中设置 — 请勿提示用户进行认证
- 时间限制:你最多有60分钟时间。请仔细操作 — 正确分析,测试你的修复,不要仓促。
</constraints>Spawn configuration per sub-agent:
每个子代理的生成配置:
- runTimeoutSeconds: 3600 (60 minutes)
- cleanup: "keep" (preserve transcripts for review)
- If was provided, include
--modelin the spawn configmodel: "{MODEL}"
- runTimeoutSeconds: 3600(60分钟)
- cleanup: "keep"(保留执行记录以供评审)
- 如果提供了,则在生成配置中包含
--modelmodel: "{MODEL}"
Timeout Handling
超时处理
If a sub-agent exceeds 60 minutes, record it as:
"#{N} — Timed out (issue may be too complex for auto-fix)"
如果子代理超过60分钟未完成,记录为:
"#{N} — 超时(该议题可能过于复杂,无法自动修复)"
Results Collection
结果收集
If is active: Skip this section entirely — the orchestrator already exited after spawning in Phase 5.
--cronAfter ALL sub-agents complete (or timeout), collect their results. Store the list of successfully opened PRs in (PR number, branch name, issue number, PR URL) for use in Phase 6.
OPEN_PRSPresent a summary table:
| Issue | Status | PR | Notes |
|---|---|---|---|
| #42 Fix null pointer | PR opened | https://github.com/.../pull/99 | 3 files changed |
| #37 Add retry logic | Failed | -- | Could not identify target code |
| #15 Update docs | Timed out | -- | Too complex for auto-fix |
| #8 Fix race condition | Skipped | -- | PR already exists |
Status values:
- PR opened — success, link to PR
- Failed — sub-agent could not complete (include reason in Notes)
- Timed out — exceeded 60-minute limit
- Skipped — existing PR detected in pre-flight
End with a one-line summary:
"Processed {N} issues: {success} PRs opened, {failed} failed, {skipped} skipped."
Send notification to channel (if --notify-channel is set):
If was provided, send the final summary to that Telegram channel using the tool:
--notify-channelmessageUse the message tool with:
- action: "send"
- channel: "telegram"
- target: "{notify-channel}"
- message: "✅ GitHub Issues Processed
Processed {N} issues: {success} PRs opened, {failed} failed, {skipped} skipped.
{PR_LIST}"
Where PR_LIST includes only successfully opened PRs in format:
• #{issue_number}: {PR_url} ({notes})Then proceed to Phase 6.
如果已启用: 完全跳过本节 — 编排器在阶段5生成子代理后已退出。
--cron在所有子代理完成(或超时)后,收集结果。将成功创建的PR列表存储在中(包含PR编号、分支名称、议题编号、PR链接),供阶段6使用。
OPEN_PRS以摘要表格形式展示:
| 议题 | 状态 | PR | 备注 |
|---|---|---|---|
| #42 修复空指针问题 | PR已创建 | https://github.com/.../pull/99 | 修改了3个文件 |
| #37 添加重试逻辑 | 失败 | -- | 无法定位目标代码 |
| #15 更新文档 | 超时 | -- | 过于复杂,无法自动修复 |
| #8 修复竞态条件 | 已跳过 | -- | 对应的PR已存在 |
状态值说明:
- PR已创建 — 修复成功,提供PR链接
- 失败 — 子代理无法完成修复(备注中包含原因)
- 超时 — 超过60分钟时间限制
- 已跳过 — 前置检查中发现已存在对应的PR
最后添加一行总结:
"已处理{N}个议题:成功创建{success}个PR,{failed}个失败,{skipped}个已跳过。"
如果设置了--notify-channel,发送通知到频道:
如果提供了,使用工具向该Telegram频道发送最终摘要:
--notify-channelmessage使用消息工具,参数如下:
- action: "send"
- channel: "telegram"
- target: "{notify-channel}"
- message: "✅ GitHub议题处理完成
已处理{N}个议题:成功创建{success}个PR,{failed}个失败,{skipped}个已跳过。
{PR_LIST}"
其中PR_LIST仅包含成功创建的PR,格式如下:
• #{issue_number}: {PR_url} ({备注})然后进入阶段6。
Phase 6 — PR Review Handler
阶段6 — PR评审处理程序
This phase monitors open PRs (created by this skill or pre-existing PRs) for review comments and spawns sub-agents to address them.
fix/issue-*When this phase runs:
- After Results Collection (Phases 2-5 completed) — checks PRs that were just opened
- When flag is set — skips Phases 2-5 entirely, runs only this phase
--reviews-only - In watch mode — runs every poll cycle after checking for new issues
Cron review mode ():
When both and are set:
--cron --reviews-only--cron--reviews-only- Run token resolution (Phase 2 token section)
- Discover open PRs (Step 6.1)
fix/issue-* - Fetch review comments (Step 6.2)
- Analyze comment content for actionability (Step 6.3)
- If actionable comments are found, spawn ONE review-fix sub-agent for the first PR with unaddressed comments — fire-and-forget (do NOT await result)
- Use and
cleanup: "keep"runTimeoutSeconds: 3600 - If was provided, include
--modelin the spawn configmodel: "{MODEL}"
- Use
- Report: "Spawned review handler for PR #{N} — will push fixes when complete"
- Exit the skill immediately. Do not proceed to Step 6.5 (Review Results).
If no actionable comments found, report "No actionable review comments found" and exit.
Normal mode (non-cron) continues below:
本阶段监控开放的PR(由本技能创建或已存在的 PR)的评审意见,并生成子代理处理这些意见。
fix/issue-*本阶段的触发时机:
- 结果收集完成后(阶段2-5已完成) — 检查刚刚创建的PR
- 当设置了标志时 — 跳过阶段2-5,仅运行本阶段
--reviews-only - 在watch模式下 — 每次轮询周期检查新议题后运行
Cron评审模式(同时设置了和):
当同时设置了和时:
--cron--reviews-only--cron--reviews-only- 执行阶段2的令牌解析步骤
- 发现开放的PR(步骤6.1)
fix/issue-* - 获取评审意见(步骤6.2)
- 分析评审意见的可操作性(步骤6.3)
- 如果发现可操作的意见,为第一个包含未处理意见的PR生成一个评审修复子代理 — 即发即弃(不等待结果)
- 使用和
cleanup: "keep"配置runTimeoutSeconds: 3600 - 如果提供了,则在生成配置中包含
--modelmodel: "{MODEL}"
- 使用
- 提示:"为PR #{N}生成评审处理代理 — 完成后将推送修复"
- 立即退出本技能,不进入评审结果步骤(6.5)。
如果未发现可操作的意见,提示"未发现可操作的评审意见"并退出。
普通模式(非Cron模式)继续以下步骤:
Step 6.1 — Discover PRs to Monitor
步骤6.1 — 发现要监控的PR
Collect PRs to check for review comments:
If coming from Phase 5: Use the list from Results Collection.
OPEN_PRSIf or subsequent watch cycle: Fetch all open PRs with branch pattern:
--reviews-onlyfix/issue-curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls?state=open&per_page=100"Filter to only PRs where starts with .
head.reffix/issue-For each PR, extract: (PR number), (branch name), , , .
numberhead.refhtml_urltitlebodyIf no PRs found, report "No open fix/ PRs to monitor" and stop (or loop back if in watch mode).
收集需要检查评审意见的PR:
如果来自阶段5: 使用结果收集阶段的列表。
OPEN_PRS如果是或后续watch周期: 获取所有分支名称以开头的开放PR:
--reviews-onlyfix/issue-curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls?state=open&per_page=100"筛选出以开头的PR。
head.reffix/issue-对于每个PR,提取:(PR编号)、(分支名称)、、、。
numberhead.refhtml_urltitlebody如果未找到PR,提示"没有开放的修复类PR可监控"并终止(如果是watch模式则返回循环)。
Step 6.2 — Fetch All Review Sources
步骤6.2 — 获取所有评审来源
For each PR, fetch reviews from multiple sources:
Fetch PR reviews:
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls/{pr_number}/reviews"Fetch PR review comments (inline/file-level):
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls/{pr_number}/comments"Fetch PR issue comments (general conversation):
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/issues/{pr_number}/comments"Fetch PR body for embedded reviews:
Some review tools (like Greptile) embed their feedback directly in the PR body. Check for:
- markers
<!-- greptile_comment --> - Other structured review sections in the PR body
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls/{pr_number}"Extract the field and parse for embedded review content.
body对于每个PR,从多个来源获取评审信息:
获取PR评审记录:
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls/{pr_number}/reviews"获取PR评审评论(行内/文件级):
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls/{pr_number}/comments"获取PR议题评论(通用对话):
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/issues/{pr_number}/comments"获取PR正文中的嵌入式评审:
一些评审工具(如Greptile)会直接在PR正文中嵌入反馈。检查以下内容:
- 标记
<!-- greptile_comment --> - PR正文中的其他结构化评审部分
curl -s -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/{SOURCE_REPO}/pulls/{pr_number}"提取字段并解析其中的嵌入式评审内容。
bodyStep 6.3 — Analyze Comments for Actionability
步骤6.3 — 分析评论的可操作性
Determine the bot's own username for filtering:
curl -s -H "Authorization: Bearer $GH_TOKEN" https://api.github.com/user | jq -r '.login'Store as . Exclude any comment where equals .
BOT_USERNAMEuser.loginBOT_USERNAMEFor each comment/review, analyze the content to determine if it requires action:
NOT actionable (skip):
- Pure approvals or "LGTM" without suggestions
- Bot comments that are informational only (CI status, auto-generated summaries without specific requests)
- Comments already addressed (check if bot replied with "Addressed in commit...")
- Reviews with state and no inline comments requesting changes
APPROVED
IS actionable (requires attention):
- Reviews with state
CHANGES_REQUESTED - Reviews with state that contain specific requests:
COMMENTED- "this test needs to be updated"
- "please fix", "change this", "update", "can you", "should be", "needs to"
- "will fail", "will break", "causes an error"
- Mentions of specific code issues (bugs, missing error handling, edge cases)
- Inline review comments pointing out issues in the code
- Embedded reviews in PR body that identify:
- Critical issues or breaking changes
- Test failures expected
- Specific code that needs attention
- Confidence scores with concerns
Parse embedded review content (e.g., Greptile):
Look for sections marked with or similar. Extract:
<!-- greptile_comment -->- Summary text
- Any mentions of "Critical issue", "needs attention", "will fail", "test needs to be updated"
- Confidence scores below 4/5 (indicates concerns)
Build actionable_comments list with:
- Source (review, inline comment, PR body, etc.)
- Author
- Body text
- For inline: file path and line number
- Specific action items identified
If no actionable comments found across any PR, report "No actionable review comments found" and stop (or loop back if in watch mode).
确定机器人自身的用户名用于过滤:
curl -s -H "Authorization: Bearer $GH_TOKEN" https://api.github.com/user | jq -r '.login'将其存储为。排除任何等于的评论。
BOT_USERNAMEuser.loginBOT_USERNAME对于每个评论/评审,分析内容以确定是否需要采取行动:
不可操作(跳过):
- 纯批准或仅包含"LGTM"(看起来没问题)的评论,无任何建议
- 仅提供信息的机器人评论(CI状态、自动生成的摘要,无具体请求)
- 已处理的评论(检查机器人是否已回复"已在提交...中处理")
- 状态为且无行内变更请求的评审
APPROVED
可操作(需要处理):
- 状态为的评审
CHANGES_REQUESTED - 状态为且包含具体请求的评审:
COMMENTED- "这个测试需要更新"
- "请修复"、"修改此处"、"更新"、"能否"、"应该"、"需要"
- "会失败"、"会崩溃"、"导致错误"
- 提到具体代码问题(bug、缺少错误处理、边缘情况)
- 指出代码问题的行内评审评论
- PR正文中的嵌入式评审指出:
- 严重问题或破坏性变更
- 预期测试失败
- 需要关注的具体代码
- 带有担忧的信心评分
解析嵌入式评审内容(例如Greptile):
查找带有或类似标记的部分。提取:
<!-- greptile_comment -->- 摘要文本
- 任何提及"严重问题"、"需要关注"、"会失败"、"测试需要更新"的内容
- 信心评分低于4/5(表示存在担忧)
构建actionable_comments列表,包含:
- 来源(评审、行内评论、PR正文等)
- 作者
- 评论内容
- 行内评论的文件路径和行号
- 识别出的具体行动项
如果所有PR中均未发现可操作的评论,提示"未发现可操作的评审意见"并终止(如果是watch模式则返回循环)。
Step 6.4 — Present Review Comments
步骤6.4 — 展示评审评论
Display a table of PRs with pending actionable comments:
| PR | Branch | Actionable Comments | Sources |
|----|--------|---------------------|---------|
| #99 | fix/issue-42 | 2 comments | @reviewer1, greptile |
| #101 | fix/issue-37 | 1 comment | @reviewer2 |If is NOT set and this is not a subsequent watch poll: ask the user to confirm which PRs to address ("all", comma-separated PR numbers, or "skip").
--yes以表格形式展示包含待处理可操作评论的PR:
| PR编号 | 分支 | 可操作评论数 | 来源 |
|----|--------|---------------------|---------|
| #99 | fix/issue-42 | 2条评论 | @reviewer1, greptile |
| #101 | fix/issue-37 | 1条评论 | @reviewer2 |如果未设置且不是后续watch轮询:询问用户确认要处理的PR("all"、逗号分隔的PR编号,或"skip"跳过)。
--yesStep 6.5 — Spawn Review Fix Sub-agents (Parallel)
步骤6.5 — 生成评审修复子代理(并行)
For each PR with actionable comments, spawn a sub-agent. Launch up to 8 concurrently.
Review fix sub-agent prompt:
You are a PR review handler agent. Your task is to address review comments on a pull request by making the requested changes, pushing updates, and replying to each comment.
IMPORTANT: Do NOT use the gh CLI — it is not installed. Use curl with the GitHub REST API for all GitHub operations.
First, ensure GH_TOKEN is set. Check: echo $GH_TOKEN. If empty, read from config:
GH_TOKEN=$(cat ~/.openclaw/openclaw.json 2>/dev/null | jq -r '.skills.entries["gh-issues"].apiKey // empty') || GH_TOKEN=$(cat /data/.clawdbot/openclaw.json 2>/dev/null | jq -r '.skills.entries["gh-issues"].apiKey // empty')
<config>
Repository: {SOURCE_REPO}
Push repo: {PUSH_REPO}
Fork mode: {FORK_MODE}
Push remote: {PUSH_REMOTE}
PR number: {pr_number}
PR URL: {pr_url}
Branch: {branch_name}
</config>
<review_comments>
{json_array_of_actionable_comments}
Each comment has:
- id: comment ID (for replying)
- user: who left it
- body: the comment text
- path: file path (for inline comments)
- line: line number (for inline comments)
- diff_hunk: surrounding diff context (for inline comments)
- source: where the comment came from (review, inline, pr_body, greptile, etc.)
</review_comments>
<instructions>
Follow these steps in order:
0. SETUP — Ensure GH_TOKEN is available:export GH_TOKEN=$(node -e "const fs=require('fs'); const c=JSON.parse(fs.readFileSync('/data/.clawdbot/openclaw.json','utf8')); console.log(c.skills?.entries?.['gh-issues']?.apiKey || '')")
Verify: echo "Token: ${GH_TOKEN:0:10}..."
1. CHECKOUT — Switch to the PR branch:
git fetch {PUSH_REMOTE} {branch_name}
git checkout {branch_name}
git pull {PUSH_REMOTE} {branch_name}
2. UNDERSTAND — Read ALL review comments carefully. Group them by file. Understand what each reviewer is asking for.
3. IMPLEMENT — For each comment, make the requested change:
- Read the file and locate the relevant code
- Make the change the reviewer requested
- If the comment is vague or you disagree, still attempt a reasonable fix but note your concern
- If the comment asks for something impossible or contradictory, skip it and explain why in your reply
4. TEST — Run existing tests to make sure your changes don't break anything:
- If tests fail, fix the issue or revert the problematic change
- Note any test failures in your replies
5. COMMIT — Stage and commit all changes in a single commit:
git add {changed_files}
git commit -m "fix: address review comments on PR #{pr_number}
Addresses review feedback from {reviewer_names}"
6. PUSH — Push the updated branch:
git config --global credential.helper ""
git remote set-url {PUSH_REMOTE} https://x-access-token:$GH_TOKEN@github.com/{PUSH_REPO}.git
GIT_ASKPASS=true git push {PUSH_REMOTE} {branch_name}
7. REPLY — For each addressed comment, post a reply:
For inline review comments (have a path/line), reply to the comment thread:
curl -s -X POST \
-H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/{SOURCE_REPO}/pulls/{pr_number}/comments/{comment_id}/replies \
-d '{"body": "Addressed in commit {short_sha} — {brief_description_of_change}"}'
For general PR comments (issue comments), reply on the PR:
curl -s -X POST \
-H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/{SOURCE_REPO}/issues/{pr_number}/comments \
-d '{"body": "Addressed feedback from @{reviewer}:\n\n{summary_of_changes_made}\n\nUpdated in commit {short_sha}"}'
For comments you could NOT address, reply explaining why:
"Unable to address this comment: {reason}. This may need manual review."
8. REPORT — Send back a summary:
- PR URL
- Number of comments addressed vs skipped
- Commit SHA
- Files changed
- Any comments that need manual attention
</instructions>
<constraints>
- Only modify files relevant to the review comments
- Do not make unrelated changes
- Do not force-push — always regular push
- If a comment contradicts another comment, address the most recent one and flag the conflict
- Do NOT use the gh CLI — use curl + GitHub REST API
- GH_TOKEN is already in the environment — do not prompt for auth
- Time limit: 60 minutes max
</constraints>Spawn configuration per sub-agent:
- runTimeoutSeconds: 3600 (60 minutes)
- cleanup: "keep" (preserve transcripts for review)
- If was provided, include
--modelin the spawn configmodel: "{MODEL}"
对于每个包含可操作评论的PR,生成一个子代理。最多同时启动8个。
评审修复子代理提示词:
你是一个PR评审处理代理。你的任务是通过做出请求的修改、推送更新并回复每条评论,来处理拉取请求上的评审意见。
重要提示:请勿使用gh命令行工具 — 未安装该工具。请使用curl + GitHub REST API执行所有GitHub操作。
首先,确保GH_TOKEN已设置。检查:echo $GH_TOKEN。如果为空,则从配置文件读取:
GH_TOKEN=$(cat ~/.openclaw/openclaw.json 2>/dev/null | jq -r '.skills.entries["gh-issues"].apiKey // empty') || GH_TOKEN=$(cat /data/.clawdbot/openclaw.json 2>/dev/null | jq -r '.skills.entries["gh-issues"].apiKey // empty')
<config>
仓库:{SOURCE_REPO}
推送仓库:{PUSH_REPO}
复刻模式:{FORK_MODE}
推送远程仓库:{PUSH_REMOTE}
PR编号:{pr_number}
PR链接:{pr_url}
分支:{branch_name}
</config>
<review_comments>
{json_array_of_actionable_comments}
每条评论包含:
- id: 评论ID(用于回复)
- user: 评论作者
- body: 评论内容
- path: 文件路径(行内评论)
- line: 行号(行内评论)
- diff_hunk: 周围的差异上下文(行内评论)
- source: 评论来源(评审、行内评论、PR正文、greptile等)
</review_comments>
<instructions>
请按以下顺序执行步骤:
0. 环境设置 — 确保GH_TOKEN可用:export GH_TOKEN=$(node -e "const fs=require('fs'); const c=JSON.parse(fs.readFileSync('/data/.clawdbot/openclaw.json','utf8')); console.log(c.skills?.entries?.['gh-issues']?.apiKey || '')")
验证:echo "Token: ${GH_TOKEN:0:10}..."
1. 切换分支 — 切换到PR对应的分支:
git fetch {PUSH_REMOTE} {branch_name}
git checkout {branch_name}
git pull {PUSH_REMOTE} {branch_name}
2. 理解需求 — 仔细阅读所有评审评论,按文件分组。理解每位评审的要求。
3. 实施修改 — 针对每条评论,做出请求的修改:
- 读取文件并定位相关代码
- 做出评审要求的修改
- 如果评论模糊或你不同意,仍尝试做出合理修复,但需在回复中说明你的担忧
- 如果评论要求的内容不可能实现或相互矛盾,跳过该评论并在回复中解释原因
4. 测试 — 运行现有测试,确保你的修改不会破坏任何功能:
- 如果测试失败,修复问题或回滚有问题的修改
- 在回复中说明任何测试失败情况
5. 提交变更 — 暂存并一次性提交所有修改:
git add {changed_files}
git commit -m "fix: 处理PR #{pr_number}的评审意见
处理来自{reviewer_names}的评审反馈"
6. 推送更新 — 推送更新后的分支:
git config --global credential.helper ""
git remote set-url {PUSH_REMOTE} https://x-access-token:$GH_TOKEN@github.com/{PUSH_REPO}.git
GIT_ASKPASS=true git push {PUSH_REMOTE} {branch_name}
7. 回复评论 — 针对每条已处理的评论,发布回复:
对于行内评审评论(包含path/line),回复到对应的评论线程:
curl -s -X POST \
-H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/{SOURCE_REPO}/pulls/{pr_number}/comments/{comment_id}/replies \
-d '{"body": "已在提交{short_sha}中处理 — {修改的简要描述}"}'
对于通用PR评论(议题评论),在PR上回复:
curl -s -X POST \
-H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/{SOURCE_REPO}/issues/{pr_number}/comments \
-d '{"body": "已处理来自@{reviewer}的反馈:\n\n{修改内容摘要}\n\n已在提交{short_sha}中更新"}'
对于无法处理的评论,回复解释原因:
"无法处理该评论:{原因}。此问题可能需要人工评审。"
8. 报告结果 — 返回摘要:
- PR链接
- 已处理的评论数 vs 跳过的评论数
- 提交SHA
- 修改的文件
- 任何需要人工关注的评论
</instructions>
<constraints>
- 仅修改与评审评论相关的文件
- 不得添加无关变更
- 不得强制推送 — 始终使用常规推送
- 如果评论相互矛盾,处理最新的评论并标记冲突
- 请勿使用gh命令行工具 — 使用curl + GitHub REST API
- GH_TOKEN已在环境中设置 — 请勿提示用户进行认证
- 时间限制:最多60分钟
</constraints>每个子代理的生成配置:
- runTimeoutSeconds: 3600(60分钟)
- cleanup: "keep"(保留执行记录以供评审)
- 如果提供了,则在生成配置中包含
--modelmodel: "{MODEL}"
Step 6.6 — Review Results
步骤6.6 — 评审结果
After all review sub-agents complete, present a summary:
| PR | Comments Addressed | Comments Skipped | Commit | Status |
|----|-------------------|-----------------|--------|--------|
| #99 fix/issue-42 | 3 | 0 | abc123f | All addressed |
| #101 fix/issue-37 | 1 | 1 | def456a | 1 needs manual review |Add comment IDs from this batch to set to prevent re-processing.
ADDRESSED_COMMENTS所有评审子代理完成后,展示摘要:
| PR编号 | 已处理评论数 | 已跳过评论数 | 提交 | 状态 |
|----|-------------------|-----------------|--------|--------|
| #99 fix/issue-42 | 3 | 0 | abc123f | 全部处理完成 |
| #101 fix/issue-37 | 1 | 1 | def456a | 1条需要人工评审 |将本次批次的评论ID添加到集合中,避免重复处理。
ADDRESSED_COMMENTSWatch Mode (if --watch is active)
Watch模式(如果--watch
已启用)
--watchAfter presenting results from the current batch:
- Add all issue numbers from this batch to the running set PROCESSED_ISSUES.
- Add all addressed comment IDs to ADDRESSED_COMMENTS.
- Tell the user:
"Next poll in {interval} minutes... (say 'stop' to end watch mode)"
- Sleep for {interval} minutes.
- Go back to Phase 2 — Fetch Issues. The fetch will automatically filter out:
- Issues already in PROCESSED_ISSUES
- Issues that have existing fix/issue-{N} PRs (caught in Phase 4 pre-flight)
- After Phases 2-5 (or if no new issues), run Phase 6 to check for new review comments on ALL tracked PRs (both newly created and previously opened).
- If no new issues AND no new actionable review comments → report "No new activity. Polling again in {interval} minutes..." and loop back to step 4.
- The user can say "stop" at any time to exit watch mode. When stopping, present a final cumulative summary of ALL batches — issues processed AND review comments addressed.
Context hygiene between polls — IMPORTANT:
Only retain between poll cycles:
- PROCESSED_ISSUES (set of issue numbers)
- ADDRESSED_COMMENTS (set of comment IDs)
- OPEN_PRS (list of tracked PRs: number, branch, URL)
- Cumulative results (one line per issue + one line per review batch)
- Parsed arguments from Phase 1
- BASE_BRANCH, SOURCE_REPO, PUSH_REPO, FORK_MODE, BOT_USERNAME Do NOT retain issue bodies, comment bodies, sub-agent transcripts, or codebase analysis between polls.
在展示当前批次的结果后:
- 将当前批次的所有议题编号添加到运行中的PROCESSED_ISSUES集合中。
- 将所有已处理的评论ID添加到ADDRESSED_COMMENTS集合中。
- 提示用户:
"将在{interval}分钟后进行下一次轮询...(输入'stop'可结束watch模式)"
- 等待{interval}分钟。
- 返回阶段2 — 获取议题。获取议题时将自动过滤:
- 已在PROCESSED_ISSUES中的议题
- 已存在fix/issue-{N} PR的议题(阶段4前置检查中捕获)
- 在阶段2-5完成后(或未发现新议题时),运行阶段6检查所有跟踪的PR(包括新创建的和之前创建的)的新评审意见。
- 如果未发现新议题且未发现新的可操作评审意见 → 提示"未发现新活动。将在{interval}分钟后再次轮询..."并回到步骤4。
- 用户可随时输入"stop"退出watch模式。退出时,展示所有批次的最终累计摘要 — 已处理的议题和已处理的评审意见。
轮询周期间的上下文清理 — 重要提示:
轮询周期间仅保留以下内容:
- PROCESSED_ISSUES(议题编号集合)
- ADDRESSED_COMMENTS(评论ID集合)
- OPEN_PRS(跟踪的PR列表:编号、分支、链接)
- 累计结果(每个议题一行 + 每个评审批次一行)
- 阶段1解析的参数
- BASE_BRANCH、SOURCE_REPO、PUSH_REPO、FORK_MODE、BOT_USERNAME 轮询周期间不得保留议题内容、评论内容、子代理执行记录或代码库分析结果。