Skip to content
🎯 场景实战第 10 / 12 节

GitHub 值班:PR 摘要与 issue 自动处理 ​

💡 一句话总结:用 OpenClaw 建立一条 7×24 的 GitHub 值班线 —— 入站 Webhook 接事件、映射钩子转任务、值班 agent 出摘要与回复。

仓库 PR 一多,人工看 diff 就跟不上;issue 里重复的提问也没人及时回。这一页带你搭一条 OpenClaw GitHub 值班线:用入站 Webhook 把仓库事件接给值班 agent,新 PR 进来自动出改动摘要,新 issue 自动分诊并起草回复。开始前请先完成《让 Claw 写代码:exec、补丁与审批》,确认你的 agent 能正常完成一轮任务。全部示例基于 OpenClaw v2026.10.9。

学完你能做什么 ​

  • 新 PR 一进仓库,值班 agent 自动产出固定格式的改动摘要:改了什么、影响哪些模块、风险在哪。
  • 新 issue 自动分诊:判断类型、识别重复问题、起草一条能直接发的回复。
  • 用 curl 在本地冒烟验证整条值班线,不用等真实 PR 上门。
  • 非目标事件(比如 push)自动返回 204,不唤醒 agent、不烧一轮对话。

为什么用 OpenClaw,而不是网页版 AI? ​

能力网页版 AIOpenClaw
7×24 响应❌ 你不开页面,它就不会动✅ Gateway 常驻运行,事件随到随处理
读仓库内容❌ 手动粘贴 diff,长了放不下✅ agent 带 GitHub 身份,自己拉 PR diff 和 issue 正文
事件驱动❌ 手动复制链接去提问✅ 入站 Webhook + 映射钩子,事件自动变成任务
留痕排查❌ 对话一关就找不回✅ 每次请求有 runId,日志可查完成状态
权限边界❌ 无✅ allowedAgentIds 限定可唤醒的 agent,写操作沿用审批

你现在的困境 ​

  • 早上打开仓库,新 PR 和新 issue 排成一列,逐个点开看 diff 要花一上午。
  • 重复的 issue 提了又提,你想先分诊打标签,但这件事本身就很耗时间。
  • 手动把 diff 粘给网页版 AI?长 diff 放不全,上下文丢失,还得盯着等结果。

什么时候用这一招 ​

  • 团队仓库每天有新 PR 和 issue,人工值班跟不上节奏。
  • 你想要格式统一的 PR 摘要,方便快速决定先看哪个。
  • issue 需要初步分诊:分类、识别重复、给提问者一个初稿回复。
  • 你已经有一台 7×24 运行 Gateway 的机器,并跑通过上一页的 exec 与审批。

🎒 开始前的准备 ​

  • 一个正在运行的 Gateway,且 agent 能正常完成一轮对话——这是官方对 webhook 的前提。
  • 一个长随机的专用 token。官方明确要求:不要复用 Gateway 认证 token 或密码。
  • GitHub 仓库的管理员权限,用来添加 Webhook。
  • 一个公网 HTTPS 入口(受信反向代理):GitHub 的服务器要能访问到你的 Gateway,认证头也由它补上(第 4 步细说)。
  • agent 读 GitHub 内容的身份:不配置 tools.github 时走 gh 原生解析,共享执行身份用 tools.github 配置(第 5 步细说)。

跟我做 ​

第 1 步:开启入站 Webhook,点亮 OpenClaw GitHub 值班线 ​

为什么先做这步:入站 Webhook 默认关闭,不开它,GitHub 的事件根本进不了 OpenClaw。

先把 hooks 配置块合并进 Gateway 配置。token 换成你的专用长随机值,main 换成值班 agent 的 id:

json5
{
  hooks: {
    enabled: true,
    token: "<long-random-hook-token>",
    path: "/hooks",
    allowedAgentIds: ["main"],
    allowRequestSessionKey: false,
  },
}

校验配置、重启服务、盯住日志:

bash
openclaw config validate
openclaw gateway restart
openclaw logs --follow

如果你是前台运行 Gateway 而不是装成服务,就手动停掉再启动那个进程。

你应该看到:openclaw config validate 通过,重启后日志里没有 hooks 相关的报错。顺带弄清这套端点的位置:它归在 Automations 指南 下(OpenClaw 2.0 起 Automations 统一命名),方向是「外部服务调用 OpenClaw」,和内部事件 hooks(HOOK.md 处理器)、自动化的外发 webhook 投递是三回事。如果 token 复用了 Gateway 共享密钥认证(gateway.auth.token / OPENCLAW_GATEWAY_TOKEN,或 gateway.auth.password / OPENCLAW_GATEWAY_PASSWORD),启动日志会记一条非致命警告,openclaw security audit 会报 critical。处理办法:openclaw doctor --fix 轮换掉已持久化的复用 token,然后更新所有外部发送方。

第 2 步:本地冒烟测试值班 agent ​

为什么要冒烟:先在本机验证端点、token、agent 接纳都正常,再放外网流量进来,出问题好定位。

另开一个终端,向本机 Gateway 的 /hooks/agent 发一条无害测试消息:

bash
curl --include http://127.0.0.1:18789/hooks/agent \
  -H 'Authorization: Bearer <long-random-hook-token>' \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: webhook-smoke-001' \
  --data '{"message":"Summarize this test event: the sample import completed.","name":"Webhook smoke test","agentId":"main","deliver":false}'

你应该看到:HTTP 200,响应体是:

json
{ "ok": true, "runId": "<hook-request-run-id>" }

注意 200 的含义:它只表示请求拿到了会话/全局的接纳,不代表模型跑完、工具成功或消息已送达;单个请求最多可能等 15 秒才被接纳。在 openclaw logs --follow 里搜 hook agent run completed 和这个 runId:status=ok 且无投递错误记 info 级;非 ok 状态(含跳过的 run)、抛错和显式投递错误记 warn 级——status=ok 但带 deliveryError 的警告表示执行成功但投递失败。

示例里 deliver: false 是冒烟测试的合理取值:成功公告被抑制、目标字段被忽略、完成结果只写日志(非 ok 结局仍会产生失败事件)。正式接 GitHub 事件时按需选:想在值班 agent 主会话收到完成通知,用默认 deliver: true,它会在目标 agent 的主会话发一条完成系统事件;只想看日志就保持 false。

第 3 步:配映射钩子,把 GitHub payload 转成 agent 任务 ​

为什么不能跳过这步:GitHub 推来的原始 payload 没有 message 字段,也带不了 Authorization: Bearer 认证头,把 Webhook 直接指向 /hooks/agent 会失败。官方为外部事件准备的机制是映射钩子:在 hooks.mappings 里为自定义路径配一个受信 JS/TS transform,由它把 payload 翻译成 agent 动作。

先在 hooks 配置里加一条映射(match.path: "gh" 匹配 /hooks/gh):

json5
{
  hooks: {
    enabled: true,
    token: "<long-random-hook-token>",
    path: "/hooks",
    allowedAgentIds: ["main"],
    allowRequestSessionKey: false,
    mappings: [
      {
        id: "github",
        match: { path: "gh" },
        action: "agent",
        agentId: "main",
        transform: { module: "gh.mjs" },
      },
    ],
  },
}

再写 transform。默认目录是 ~/.openclaw/hooks/transforms(配置键 transformsDir);transform 是受信的 Gateway 代码、会被缓存,改完要重启才生效:

js
// ~/.openclaw/hooks/transforms/gh.mjs
export default function transform({ payload, headers }) {
  const event = headers["x-github-event"] ?? headers["X-GitHub-Event"];

  if (event === "pull_request" && payload.action === "opened") {
    const pr = payload.pull_request;
    return {
      kind: "agent",
      message:
        `新 PR #${payload.number}:${pr.title}\n` +
        `作者 ${pr.user.login},分支 ${pr.head.ref} → ${pr.base.ref}\n` +
        `请拉取该 PR 的 diff,按「PR 改动摘要」规范输出。`,
    };
  }

  if (event === "issues" && payload.action === "opened") {
    return {
      kind: "agent",
      message:
        `新 issue #${payload.number}:${payload.issue.title}\n` +
        `正文:${payload.issue.body ?? "(空)"}\n` +
        `请按「issue 分诊与回复起草」规范分类并起草回复。`,
    };
  }

  // 非目标事件(如 push):返回 null,OpenClaw 回 204,不创建 run
  return null;
}

payload 里的字段名(action、number、pull_request 等)以 GitHub 官方的 webhook 交付格式为准,接线前对照一次实际收到的事件。事件格式简单的话,也可以不写 JS,用映射自带的 messageTemplate 模板字段拼 message;GitHub 事件要按类型分支、还要过滤非目标事件,所以这里用 transform。

校验、重启,然后本地模拟两种事件各打一发:

bash
openclaw config validate
openclaw gateway restart
bash
# 模拟新 PR:期望 200 + runId
curl --include http://127.0.0.1:18789/hooks/gh \
  -H 'Authorization: Bearer <long-random-hook-token>' \
  -H 'Content-Type: application/json' \
  -H 'X-GitHub-Event: pull_request' \
  --data '{"action":"opened","number":42,"pull_request":{"title":"Add export button","user":{"login":"alice"},"head":{"ref":"feat/export"},"base":{"ref":"main"}}}'

# 模拟 push:期望 204
curl --include http://127.0.0.1:18789/hooks/gh \
  -H 'Authorization: Bearer <long-random-hook-token>' \
  -H 'Content-Type: application/json' \
  -H 'X-GitHub-Event: push' \
  --data '{"ref":"refs/heads/main"}'

你应该看到:模拟 PR 返回 HTTP 200 和 { "ok": true, "runId": "<hook-request-run-id>" };模拟 push 返回 HTTP 204——transform 返回了 null,映射故意不产生动作,连 run 都不会创建。

💡 这就是 OpenClaw 的独有价值

映射钩子是通用的「外部事件翻译层」:今天接 GitHub,明天换一个代码托管平台或监控告警,都只是换一个 transform 文件的事。payload 没有 message?transform 里生成。不想让无关事件烧掉一轮对话?返回 null,OpenClaw 回 204。这是网页版 AI 给不了的事件级接线能力。

第 4 步:在 GitHub 仓库挂上 Webhook ​

为什么要反向代理:官方要求 hook 端点保持在 loopback、tailnet 或受信反向代理之后,远程调用走 HTTPS。GitHub 在公网、你的 Gateway 在内网,中间由受信反向代理转发并补上认证头。

在仓库设置的 Webhooks 页新增一个 hook:

  • Payload URL:https://<你的公网域名>/hooks/gh——由反向代理转发到 Gateway,并补上 Authorization: Bearer <long-random-hook-token> 请求头。
  • Content type:选 JSON。OpenClaw 的 hook 端点只接受 Content-Type: application/json 的 POST。
  • 触发事件:只勾 Pull requests 和 Issues 两类,别开全量事件——非目标事件虽然会被 transform 用 204 挡掉,但没必要让 GitHub 白投一轮。
  • Secret:GitHub 侧的投递签名密钥 。

代理侧只暴露必需的那条路径,别把整个 Gateway 端口裸露到公网。

你应该看到:GitHub 的 Webhook 投递记录里,目标事件返回 200、非目标事件返回 204;openclaw logs --follow 里出现 hook agent run completed 和对应 runId。

第 5 步:给值班 agent 配 GitHub 身份 ​

为什么需要这步:webhook payload 只带标题、作者这类元信息;摘要和分诊要靠谱,agent 得自己拉 PR diff 和 issue 正文,这需要一个 GitHub 身份。

方式 A(推荐先跑通):什么都不配。GitHub CLI 身份默认原生解析——Gateway 进程的 GH_TOKEN 或 GITHUB_TOKEN 环境变量优先,其次运行用户的 gh keyring/config。在跑 Gateway 的机器上完成 gh auth login(或给 Gateway 进程配好环境变量)就行。

方式 B(长期值班):配 tools.github 共享执行身份,凭据由 Gateway 托管。在 Control UI 的 Settings → Profile → GitHub connections 里,管理员选择 For the system 发起连接:打开 https://github.com/login/device,粘贴 OpenClaw 显示的一次性代码,批准 repo、workflow、read:org、gist 四个权限。连接成功后,配置里会出现这样一段:

json5
{
  tools: {
    github: {
      profileId: "ghp_0123456789abcdef0123456789abcdef",
      kind: "oauth",
      gitAuthor: { name: "Automation User", email: "automation@example.com" },
    },
  },
}

三个边界要知道:

  • OAuth access token 大约 8 小时过期,Gateway 会在过期前自动刷新;刷新令牌失效会显示 Reconnect required。
  • kind: "app-installation" 的 App 身份只支持前台会话读取;要让 agent 跑工具,选 native 或 OAuth。
  • 某个 agent 要用不同身份时,在 agents.entries.<id>.tools.github 里覆盖,不配则继承系统身份;不想走 OAuth,也可以选 Use a PAT instead,保留细粒度个人访问令牌的设置路径。

你应该看到:值班 agent 在会话里能拉到 PR diff 和 issue 正文;如果配了托管身份但凭据缺失或失效,GitHub 状态会报 configured_unavailable,而不是悄悄回落到本机账号。

📋 魔法 Prompt ​

transform 只负责把事件翻译成一条 message;agent 拿到 message 后怎么做,由它工作区里的常驻指令决定。把下面两段写进值班 agent 的 AGENTS.md(个人安装默认在 ~/.openclaw/workspace)——transform 生成的 message 里引用的正是这两段规范的名字。

📝 PR 改动摘要 ​

预期效果:新 PR 事件进来后,agent 产出固定格式的摘要——改了什么、影响哪些模块、风险在哪,你不用点开 diff 就能决定先看哪个。

text
角色:你是本仓库的值班 reviewer,为新开的 PR 产出改动摘要。
任务:拉取 PR 的 diff 与描述,按输出规范产出摘要。
输入信息:
### 必填项
- 【PR 编号】
- 【PR 标题】
- 【作者】
- 【分支(head → base)】
### 选填项
- 【PR 描述?】
- 【关联 issue?】
输出规范:
- 第一行:一句话概括这个 PR 做了什么。
- 改动清单:按模块分组,每条一行,标注新增/修改/删除。
- 影响面:受影响的功能、接口或配置。
- 风险:测试缺口、破坏性变更、需要人工重点看的文件。
约束条件:
✅ 只依据 diff 与 PR 描述,不猜测没写出来的意图
✅ 摘要不超过 20 行
❌ 不给「可合并」这类审查结论,决定留给人
❌ 不修改代码、不推送分支

📋 issue 分诊与回复起草 ​

预期效果:新 issue 自动判断类型、识别重复问题,并起草一条可以直接发出去的回复。

text
角色:你是本仓库的值班 triager,为新 issue 分诊并起草回复。
任务:读 issue 标题与正文,判断类型、查重、起草回复草稿。
输入信息:
### 必填项
- 【issue 编号】
- 【issue 标题】
### 选填项
- 【issue 正文?】
- 【仓库内相似 issue 的编号列表?】
输出规范:
- 类型:bug / 功能请求 / 文档 / 使用问题 / 其他,五选一。
- 重复判断:疑似重复时给出已有 issue 编号;查不到就写「未发现重复」。
- 回复草稿:一段可直接发出的中文回复——确认理解、给出下一步。
约束条件:
✅ 信息不足时,在草稿里列出需要提问者补充的内容
✅ 语气具体、礼貌,不敷衍
❌ 不自行关闭 issue、不改仓库文件
❌ 不承诺修复时间或版本

检查点 ✅ ​

整条值班线跑通的标准,逐条对照:

  • openclaw config validate 通过,重启后日志里没有 hooks 报错。
  • 第 2 步的 curl 冒烟返回 200,响应体里有 runId。
  • 第 3 步:模拟 pull_request 返回 200,模拟 push 返回 204(不创建 run)。
  • 第 4 步:GitHub 的 Webhook 投递记录里出现 200/204,openclaw logs --follow 里能搜到 hook agent run completed。
  • 第 5 步:值班 agent 在会话里能拉到 PR diff 和 issue 正文。
  • 完成日志是 status=ok;如果看到 status=ok 带 deliveryError 的 warn,是执行成功但投递失败,去查投递目标。

踩坑提醒 ​

现象多半是怎么处理
401hook token 不对,或代理没转发认证头核对专用 hook token(不是 Gateway auth);检查代理是否原样转发 Authorization 头
404hooks.enabled、hooks.path 或映射路径没对上确认 match.path: "gh" 匹配 /hooks/gh;自定义路径别叫 agent 或 wake,直连端点优先
204映射故意不产生动作不是错误:transform 返回 null 或空 fan-out 都会 204
200 但没收到消息deliver: false 抑制了成功公告先查完成日志;要投递就给映射配明确的 channel 和 to
500transform 抛异常看日志里的 hook mapping failed,修好 transform 再重启

三条安全底线,别省:

  • 专用 token、专用子路径:hook token 与 Gateway 共享密钥认证分开;/ 作为路径会被拒绝。
  • 只暴露必需路径:端点放 loopback、tailnet 或受信反向代理之后,远程调用走 HTTPS。
  • 外部内容当数据:payload 默认会被 safety-wrapped,但包装不会移除 agent 的工具和工作区访问——处理不可信输入用受限 agent,保持 allowUnsafeExternalContent 关闭。

本课小结 ​

  • 一条 OpenClaw GitHub 值班线由四件东西组成:入站 Webhook 开门、映射钩子翻译、值班 agent 干活、GitHub 身份读仓库。
  • 值得带走三件事:hooks.mappings 能把任意外部 payload 转成 agent 动作;transform 返回 null 用 204 挡掉非目标事件、不创建 run;deliver 决定完成事件要不要投回主会话。
  • 安全底线三条:专用 token、只暴露必需路径、外部内容当数据。
  • PR 摘要和 issue 分诊都只产出「草稿与判断」,合并、关闭这类决定留给人——这是值班,不是放权。

下一课预告 ​

值班线跑通后你大概会想:PR 审查和 issue 分诊挤在同一个 agent 的指令里,能不能各请一位专家?下一课《多 Agent 协作:一个 Gateway 跑多个专家》讲怎么在一个 Gateway 里跑多个相互隔离的 agent——各自有独立的 workspace 和会话历史,用 bindings 把不同消息路由给不同专家,把今天的值班线拆成「PR 专家 + issue 专家」。

搞懂AI关于我们怎么写隐私说明

独立的第三方教程,与文中提到的任何产品及其公司没有隶属或合作关系;产品名称和商标归各自所有者。价格和政策以官方页面为准。