Kilo 仓库重复 PR 检测 Agent 实战解析:从 Agent 定义、GitHub PR 搜索工具到自动化工作流 Kilo 仓库重复 PR 检测 Agent 实战解析从 Agent 定义、GitHub PR 搜索工具到自动化工作流【免费下载链接】kilocodeKilo is the all-in-one agentic engineering platform. Build, ship, and iterate faster with the most popular open source coding agent.项目地址: https://gitcode.com/GitHub_Trending/ki/kilocode在开源仓库中多个贡献者针对同一 issue 或功能提交多个 PR 是常见现象。重复 PR 会浪费维护者审阅精力、增加合并冲突风险也让贡献者感到困惑。本文以 Kilo 仓库中真实存在的.opencode/agent/duplicate-pr.md为核心完整拆解这个重复 PR 检测 Agent的设计从 frontmatter 配置、系统提示词的行为契约到其依赖的github-pr-search工具实现、script/duplicate-pr.ts调用脚本再到曾经承载它的 GitHub Actions 工作流让读者理解如何用声明式 Agent 定义 工具白名单 精确输出契约的方式把一个重复 PR 检测任务做成可复用、可自动化的工程能力。一、总体架构一个 Agent 的四层构成duplicate-pr检测 Agent 在 Kilo 仓库中由四个可独立查看的部件组成构成一条完整的定义 → 工具 → 调用 → 自动化链路层仓库路径作用Agent 定义.opencode/agent/duplicate-pr.md声明模型、工具白名单与行为规范核心主体工具实现.opencode/tool/github-pr-search.ts通过 GitHub Search API 检索开放 PR调用脚本script/duplicate-pr.ts用kilocode/sdk启动 Kilo 会话并指定duplicate-prAgent自动化工作流.github/workflows/disabled/pr-management.yml.disabled在 PR 打开事件上触发检测并回帖当前处于 disabled 状态其中 Agent 定义是整个方案的灵魂它不写死任何检索逻辑而是通过约束模型该做什么、能调用什么工具、以什么格式输出把重复 PR 检测变成可被 LLM 稳定执行的确定性流程。二、Agent 定义逐段拆解.opencode/agent/duplicate-pr.md2.1 frontmatter声明式配置的关键字段该文件开头的 YAML frontmatter 定义了 Agent 的运行元数据--- mode: primary hidden: true model: kilo/anthropic/claude-haiku-4.5 color: #E67E22 tools: *: false github-pr-search: true ---各字段含义与设计意图如下mode: primary声明这是主 Agentprimary agent与同目录下的 triage Agent.opencode/agent/triage.md一致表示它可被会话直接调用执行主任务而非仅作为辅助参考。mode取值为 primary/secondary/all 中的一种从源码结构看两个 agent 均声明 primaryprimary 用于承载完整任务执行。hidden: true该 Agent 不在用户可见的 Agent 列表中展示属于后台自动化用途避免干扰用户手动选择 Agent 的界面。model: kilo/anthropic/claude-haiku-4.5指定运行模型为 Claude Haiku 4.5。选择轻量快速模型与任务性质匹配——重复 PR 检测是高频、低复杂度、对响应速度敏感的任务不需要重型推理模型。color: #E67E22为 Agent 分配的界面标识色橙色用于在 UI 中区分不同 Agent。tools白名单这是最关键的权限设计。*: false表示默认禁用所有工具然后显式启用github-pr-search: true。这种默认全禁、按需放行的最小权限原则能显著降低模型误用工具的风险也是可审计、可预期的 Agent 设计范式。2.2 系统提示词把任务规范拆成可执行契约frontmatter 之后是系统提示词正文它把检测重复 PR这一目标分解为五条明确指令逐条解读如下1角色与任务声明You are a duplicate PR detection agent. When a PR is opened, your job is to search for potentially duplicate or related open PRs.明确了 Agent 的身份重复 PR 检测员与触发时机PR 被打开时职责边界被限定在搜索可能与当前 PR 重复或相关的开放 PR。2工具使用指令Use the github-pr-search tool to search for PRs that might be addressing the same issue or feature.强制指定唯一的工具入口避免模型自行编造检索方式或调用未授权的其他工具。3自排除保护IMPORTANT: The input will contain a lineCURRENT_PR_NUMBER: NNNN. This is the current PR number, you should not mark that the current PR as a duplicate of itself.这是防止PR 与自己匹配的护栏。调用方必须在输入中携带CURRENT_PR_NUMBER: NNNN格式的行NNNN 为当前 PR 编号Agent 必须排除自身。该字段由工作流脚本通过 GitHub 事件负载注入详见下文第四节。4多轮检索策略Search using keywords from the PR title and description. Try multiple searches with different relevant terms.要求从标题与描述中抽取关键词并用多个不同的相关词进行多次搜索。这背后的原因很实际GitHub 的 issue/PR 搜索是全文关键词匹配不同贡献者描述同一功能时用词可能完全不同例如 dark mode 与 theme toggle单次搜索极易漏检多关键词轮询才能覆盖语义变体。5输出契约If you find potential duplicates: List them with their titles and URLs, briefly explain why they might be related. If no duplicates are found, say so clearly. BUT ONLY SAY No duplicate PRs found (dont say anything else if no dups). Keep your response concise and actionable.输出格式被严格规定为两种找到候选时列出 PR 标题 URL并简述相关性理由未找到时只能输出恰好一句No duplicate PRs found不得输出任何其他内容。这个精确的输出契约sentinel 值是后续自动化工作流判断分支的关键——工作流正是通过比对返回值是否等于No duplicate PRs found来决定是否回帖见第四节这体现了Agent 输出即程序输入的工程化思想。三、工具实现github-pr-search 的底层原理Agent 被授权使用的唯一工具定义在 .opencode/tool/github-pr-search.ts它基于kilocode/plugin的tool()API 声明。3.1 参数 Schemaargs: { query: tool.schema.string().describe(Search query for PR titles and descriptions), limit: tool.schema.number().describe(Maximum number of results to return).default(10), offset: tool.schema.number().describe(Number of results to skip for pagination).default(0), },三个参数必填的query搜索关键词可选的limit默认 10与offset默认 0用于翻页。这为模型提供了分页能力当候选较多时可继续翻页获取更多结果。3.2 GitHub API 调用工具内部通过 REST API 的 Search Issues 端点检索 PRconst page Math.floor(args.offset / args.limit) 1 const searchQuery encodeURIComponent(${args.query} repo:${owner}/${repo} type:pr state:open) const result await githubFetch( /search/issues?q${searchQuery}per_page${args.limit}page${page}sortupdatedorderdesc, )关键细节限定检索范围查询串强制附加repo:anomalyco/opencode当前仓库的上游 fork 命名仓库被 fork 到 Kilo 后沿用与type:pr state:open即只搜索指定仓库中状态为 open 的 PR从源头排除了已合并/已关闭的 PR 和 issue排序按updated倒序让最近有活动的 PR 排在最前鉴权请求头携带Authorization: Bearer ${process.env.GITHUB_TOKEN}详见 .opencode/tool/github-pr-search.ts 的githubFetch封装环境变量GITHUB_TOKEN由调用方注入错误处理非 2xx 响应抛出GitHub API error: status statusText便于上层脚本捕获。3.3 输出格式化const formatted prs.map((pr) ${pr.title}\n${pr.html_url}).join(\n\n) return Found ${result.total_count} PRs (showing ${prs.length}):\n\n${formatted}结果以 标题 URL 成对呈现且开头给出total_count命中总数与本次实际展示数量方便模型判断是否需要翻页继续检索。无命中时分别返回No PRs found matching ...与No other PRs found matching ...两种提示。工具描述中声明其返回 LLM-friendly 结果包含 PR 编号、标题、作者、状态open/closed/merged、标签与描述片段。值得一提的是.opencode/opencode.jsonc全局配置中tools.github-pr-search与tools.github-triage均被置为false说明该工具默认不向普通会话开放仅在duplicate-prAgent 的白名单中被显式启用——与 frontmatter 的*: false策略形成全局关闭、局部放行的双重保险。四、调用脚本script/duplicate-pr.tsscript/duplicate-pr.ts 是用 Bun 编写的 CLI 脚本负责把 PR 信息交给duplicate-prAgent 并取回结论。4.1 用法与参数Usage: bun script/duplicate-pr.ts [options] message Options: -f, --file path File to attach to the prompt -h, --help Show this help message Examples: bun script/duplicate-pr.ts -f pr_info.txt Check the attached file for PR detailsmessage直接作为文本消息发送给 Agent-f, --file将指定文件如pr_info.txt作为附件附加到提示词中。脚本内部用Bun.file()校验文件存在性并通过pathToFileURL把本地路径转为file://URL以{ type: file, url, filename, mime: text/plain }的形式拼入消息 parts——这正是工作流注入CURRENT_PR_NUMBER与 PR 标题/描述的载体。4.2 会话执行流程const opencode await createKilo({ port: 0 }) const session await opencode.client.session.create() const result await opencode.client.session.prompt({ path: { id: session.data!.id }, body: { agent: duplicate-pr, parts }, signal: AbortSignal.timeout(120_000), }).then((x) x.data?.parts?.find((y) y.type text)?.text ?? ) console.log(result.trim())流程要点createKilo({ port: 0 })以随机端口启动本地 Kilo 服务器port: 0表示由系统分配空闲端口通过kilocode/sdk的 client 与其通信创建会话后在body中显式指定agent: duplicate-pr即把会话路由到本文讨论的 Agent 定义请求设置AbortSignal.timeout(120_000)的 120 秒超时上限防止模型无限挂起结果从响应的 text parts 中提取并trim()后打印到 stdout——该 stdout 输出正是工作流断言分支的依据执行完毕后opencode.server.close()关闭服务器避免残留进程。五、自动化落地pr-management 工作流disabled.github/workflows/disabled/pr-management.yml.disabled展示了该 Agent 曾经承载的端到端自动化文件后缀.disabled表示当前在 CI 中停用仅作历史参考。5.1 触发与前置过滤工作流由pull_request_target事件在types: [opened]时触发即仅在新 PR 打开的瞬间运行。第一步是团队成员过滤若 PR 作者是opencode-agent[bot]或位于.github/TEAM_MEMBERS名单中则跳过整个检测流程——内部成员与机器人提交的 PR 不再重复检查节省算力并避免打扰。5.2 构造 Agent 输入run: | { echo Check for duplicate PRs related to this new PR: echo echo CURRENT_PR_NUMBER: $PR_NUMBER echo echo Title: $(gh pr view $PR_NUMBER --json title --jq .title) echo echo Description: gh pr view $PR_NUMBER --json body --jq .body } pr_info.txt这里通过gh pr view抓取当前 PR 的编号、标题与描述写入pr_info.txt其中CURRENT_PR_NUMBER: $PR_NUMBER这一行正是 Agent 提示词中不得把自己判为重复的护栏输入。5.3 执行检测并回帖COMMENT$(bun script/duplicate-pr.ts -f pr_info.txt Check the attached file for PR details and search for duplicates) if [ $COMMENT ! No duplicate PRs found ]; then gh pr comment $PR_NUMBER --body _The following comment was made by an LLM, it may be inaccurate:_ $COMMENT fi这段逻辑完整印证了第二节的输出契约设计将pr_info.txt作为附件、检索指令作为消息运行duplicate-pr.ts以字符串精确比对No duplicate PRs found作为分支条件——只有未找到重复时才静默跳过找到候选时通过gh pr comment回帖帖子以斜体免责声明 The following comment was made by an LLM, it may be inaccurate: 开头明确标注内容由 LLM 生成、可能存在不准确之处。这种AI 建议 人类兜底的姿态是机器人参与维护流程的稳妥实践。5.4 同批次的关联维护该工作流还包含一个add-contributor-labeljob当作者关联为CONTRIBUTOR时自动为 PR 打上contributor标签属于 PR 打开时刻配套的贡献者激励流程。六、设计模式总结与 triage Agent 的对照仓库中与duplicate-pr同构的还有 issue 分流 Agent .opencode/agent/triage.md两者对照可提炼出本仓库 Agent 化的通用模式维度duplicate-prtriage模型kilo/anthropic/claude-haiku-4.5kilo/openai/gpt-5-nano工具白名单仅github-pr-search仅github-triage输入契约CURRENT_PR_NUMBER行 PR 标题/描述待分流 issue 内容 固定团队枚举输出契约精确哨兵串No duplicate PRs found或候选列表按 7 个团队枚举赋值负责人禁止添加标签共同点非常明显mode: primaryhidden: true 单一领域工具白名单 严格的输入/输出契约。这类 Agent 本质上是以 LLM 为执行引擎、以文档为规范、以工具为唯一动作入口的声明式自动化单元既保留了 LLM 对自然语言的语义理解能力多关键词检索、相关性判断又通过工具白名单与输出契约把不确定性压缩到可编程消费的范围内。七、部署与运行前提若要在本地复现该 Agent 的检测能力需要满足安装依赖项目根目录执行bun installBun 是项目脚本的运行时准备环境变量GITHUB_TOKENGitHub API 鉴权用于github-pr-search工具与OPENCODE_API_KEYKilo API 密钥用于启动 LLM 会话运行脚本先构造包含CURRENT_PR_NUMBER与 PR 信息的pr_info.txt再执行bun script/duplicate-pr.ts -f pr_info.txt Check the attached file for PR details and search for duplicates理解输出stdout 若为No duplicate PRs found表示未发现重复否则为候选 PR 的标题 URL列表及相关性说明。注意仓库中该自动化工作流当前以.disabled后缀停用可在 .github/workflows/disabled/pr-management.yml.disabled 查看其完整历史实现工具实现中检索的repo:anomalyco/opencode为上游 fork 命名空间若在其它仓库使用需相应调整。此外仓库另有.github/workflows/kilo-auto-close.yml负责定期关闭长期无活动的 PR 与 issue与重复 PR 检测形成新 PR 打开时查重、长期无活动时回收的互补治理闭环。结语从.opencode/agent/duplicate-pr.md这一份不足 30 行的 Agent 定义出发可以完整看到 Kilo 仓库如何把一个PR 查重的琐碎维护任务工程化用 frontmatter 声明模型与工具权限用系统提示词固化检索策略与输出契约用github-pr-search工具隔离 GitHub API 细节用script/duplicate-pr.ts统一调用入口再用工作流脚本把Agent 输出变成回帖决策。这套声明式 Agent 最小工具白名单 哨兵输出契约的模式值得任何希望在 CI 流水线中引入 LLM 自动化判断的团队借鉴。【免费下载链接】kilocodeKilo is the all-in-one agentic engineering platform. Build, ship, and iterate faster with the most popular open source coding agent.项目地址: https://gitcode.com/GitHub_Trending/ki/kilocode创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考