尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Claude Managed Agents 如何编排 issue 到 PR:CI 失败与评审意见中途恢复

Claude Managed Agents 如何编排 issue 到 PR:CI 失败与评审意见中途恢复 Claude Managed Agents 如何编排 issue 到 PRCI 失败与评审意见中途恢复【免费下载链接】claude-cookbooksA collection of notebooks/recipes showcasing some fun and effective ways of using Claude.项目地址: https://gitcode.com/GitHub_Trending/an/claude-cookbooks这篇文章解决的问题是如何让一个 Claude Managed Agents 会话独立走完「读 issue → 定位 bug → 修复 → 开 PR → 跑 CI → 处理评审意见 → 合并」这条完整维护者流程并且在中途遇到 CI 失败和评审 bot 打回时能读取输出、修正后继续而不是盲目重试。教程来自 claude-cookbooks 仓库的 CMA_orchestrate_issue_to_pr.ipynb它用一个自带埋点的 mock 仓库issue #42 的 Unicode slug 缺陷把两个恢复点固定下来一次 CI 失败和一次 reviewer-bot 的 CHANGES_REQUESTED。前置条件设置ANTHROPIC_API_KEY环境变量Python 环境满足 managed_agents/pyproject.toml 中声明的3.11,3.13依赖为anthropic0.109.0和python-dotenv。模型可通过环境变量COOKBOOK_MODEL指定默认值为claude-sonnet-4-4-6之外的笔记默认值claude-sonnet-4-6——即MODEL os.environ.get(COOKBOOK_MODEL, claude-sonnet-4-6)不设置时使用文档给出的默认模型。准备条件mock 仓库里埋了什么fixture 位于 managed_agents/example_data/orchestrate/包含issue_42.json一个含糊的 bug 报告。标题是 Blog post URLs with accented characters 404正文只说slugify(Café Culture)得到caf-culture而不是cafe-culture并暗示问题在 url_utils.py 或 blog.py 的调用处——agent 必须读代码才能定位根因是slugify()里的.encode(ascii, ignore)丢弃了重音字符。tests/test_urls.py包含test_slugify_unicode、test_post_url_unicode等用例在 bug 修复前必然失败充当 CI 的执行体。gh-mock一个 bash 脚本模拟ghCLI 的关键子命令全部状态持久化在.gh-state/目录因此每一步都能看到上一步的结果子命令行为issue view n打印issue_n.json内容pr create固定创建 PR #101初始checks.ci/test为pendingpr checks实际运行python3 -m pytest tests/ -q --tbshort按返回码把ci/test写成pass/fail失败时打印 pytest 输出并以非零退出pr review检查src/url_utils.py中slugify()函数体是否含没有则追加CHANGES_REQUESTED评审要求补 docstring有则追加APPROVEDpr merge要求ci/test为pass且存在APPROVED评审否则退出非零满足则把state写为merged这两个评审点就是标题中的「中途恢复」CI 会失败例如第一次修复只处理了é漏掉üpr checks退出非零并打印 pytest 输出reviewer-bot 会在slugify()缺 docstring 时挡住合并。fixture 的 README 给出了健康运行的终态判定.gh-state/pr_101.json中state: merged、ci/test: pass、存在一条APPROVED评审。配置 agent、environment 和 session注意 notebook 的相对路径约定代码在managed_agents/目录下运行fixture 相对路径是example_data/orchestrate。第一步把 fixture 打成内存 zip跳过README.md并上传为文件资源后续挂载进会话import io import os import zipfile from pathlib import Path from anthropic import Anthropic from utilities import stream_until_end_turn, wait_for_idle_status MODEL os.environ.get(COOKBOOK_MODEL, claude-sonnet-4-6) GH_TOKEN os.environ.get(GITHUB_TOKEN) # only needed for the github_repository sidebar client Anthropic() FIXTURE Path(example_data) / orchestrate buf io.BytesIO() with zipfile.ZipFile(buf, w) as zf: for f in FIXTURE.rglob(*): if f.is_file() and f.name ! README.md: zf.write(f, f.relative_to(FIXTURE)) buf.seek(0) fixture_zip client.beta.files.upload(file(repo.zip, buf, application/zip)) print(ffixture: {fixture_zip.id})第二步创建 agent、environment、session。这里有一个关键配置环境声明了pytest作为 pip 依赖并开启allow_package_managers: True因为 agent 要在容器里真实运行测试套件作为 CI 循环的一部分。这是该 notebook 首次需要联网安装包的地方——网络配置保持limited只放行包管理器agent client.beta.agents.create( namecookbook-orchestrate, modelMODEL, system( You are a maintainer bot. You read issues via ./gh-mock, explore the codebase, write fixes, and shepherd PRs through CI and review. When CI fails or a reviewer requests changes, read what they said and address it, dont just retry blindly.\n\n Work in /mnt/user. All gh-mock commands run from there. ), tools[ { type: agent_toolset_20260401, default_config: { enabled: True, permission_policy: {type: always_allow}, }, } ], ) env client.beta.environments.create( namecookbook-orchestrate-env, config{ type: cloud, networking: {type: limited, allow_package_managers: True}, packages: {pip: [pytest]}, }, ) session client.beta.sessions.create( environment_idenv.id, agent{type: agent, id: agent.id, version: agent.version}, resources[{type: file, file_id: fixture_zip.id, mount_path: repo.zip}], titleIssue #42 → PR, ) print(fsession: {session.id})system prompt 里那句「read what they said and address it, dont just retry blindly」是整个编排的指令核心它要求 agent 在 CI 失败或评审打回时先读取输出再行动。工具集agent_toolset_20260401配always_allow让 agent 可以自由执行 bash/read/grep 等工具不需要人工放行。发起完整编排链整条链由一条user.message触发消息本身要求 agent 先读./gh-mock脚本了解支持的子命令再用这些子命令完成查看 issue、开 PR、跑 CI、处理评审、合并client.beta.sessions.events.send( session_idsession.id, events[ { type: user.message, content: [ { type: text, text: ( Unpack /mnt/session/uploads/repo.zip into /mnt/user and ship a fix for issue #42 end-to-end. Read the ./gh-mock script first to see what subcommands it supports; use those to view the issue, open a PR, run CI, handle review feedback, and merge. Show me the final PR state when youre done. ), } ], } ], ) print( full orchestrate chain ) stream_until_end_turn(client, session.id)stream_until_end_turn是 managed_agents/utilities.py 中的公共 helper它流式打印agent.message文本、标记每次agent.tool_use在session.status_idle且stop_reason.type end_turn时退出退出后再短暂轮询确认服务端状态回到idle避免立刻archive()撞上 400 竞态。运行过程中有两个观察点CI 失败点。如果 agent 的第一版修复不完整比如只转写了é而漏掉ügh-mock pr checks会退出非零并带上 pytest 输出pr checks把stdout stderr的最后 800 字符存入pr_101.json的checks._last_output。agent 需要读这份 traceback 再迭代这是本例要验证的中途恢复能力之一。评审打回点。CI 转绿后gh-mock pr review检查slugify()是否带 docstring。缺失时输出Review: CHANGES_REQUESTED Please add a docstring to slugify() explaining the unicode handling.此时pr merge会因「needs an approving review」退出非零agent 补上 docstring 后重新评审才能得到APPROVED。状态在链上按 issue 正文 → 文件路径 → 修复 diff → PR 号 → CI 输出 → 评审意见 → 最终合并流动gh-mock把每一步持久化到.gh-state/后一步总能看到前一步做了什么。多轮验证最终状态Managed Agents 的会话是有状态的容器文件系统和对话历史跨轮次保留所以验证只需在同一 session 再发一条user.message。notebook 选择直接打印 mock CLI 持久化的 PR 状态文件——这是最简的独立核对方式client.beta.sessions.events.send( session_idsession.id, events[ { type: user.message, content: [ { type: text, text: ( Print the contents of /mnt/user/.gh-state/pr_101.json so I can see the final state, CI status, and reviews. ), } ], } ], ) stream_until_end_turn(client, session.id) wait_for_idle_status(client, session.id) client.beta.sessions.archive(session.id) client.beta.environments.archive(env.id) client.beta.agents.archive(agent.id) print(archived)成功判定以 fixture README 给出的终态为准/mnt/user/.gh-state/pr_101.json里state为merged、checks.ci/test为pass、reviews中至少一条state为APPROVED。pr merge脚本本身的两个前置检查CI 必须 pass、必须有 APPROVED 评审就是 merge 能否成功的完整条件不需要额外推断。限制与可选分支主流程完全离线不需要 GitHub 凭据GITHUB_TOKEN只在下述真实仓库 sidebar 中才用到主链可以不设置。网络限制是刻意的环境为limited仅allow_package_managers: True放行 pip 安装pytest。如果你的 agent 还需要其他包按同一方式加入packages.pip列表。可选分支挂载真实 GitHub 仓库。把会话资源里的{type: file, ...}换成github_repository资源API 会在会话创建时把仓库 clone 进容器clone 只发生一次后续轮次复用同一工作树。真实仓库尤其是私有仓库需要GITHUB_TOKEN。示例形态session client.beta.sessions.create( environment_idenv.id, agent{type: agent, id: agent.id, version: agent.version}, resources[ { type: github_repository, url: https://github.com/anthropics/claude-cookbooks, mount_path: /workspace/cookbook, authorization_token: GH_TOKEN, checkout: {type: branch, name: main}, } ], titleRepo explorer, )该resources字段是列表github_repository与file混用即可例如同时 clone 仓库和挂载一个配置文件。另外如果仓库根目录有.claude/skills/其中每个 skill 会在会话启动时被发现并注入 agent无需在 agent 上声明skills字段这一机制在 CMA_use_skills_from_a_repo.ipynb 中有单独讲解。切换到真实仓库后gh-mock对应的就是真实ghCLI 或仓库自带 CI本文的 mock 终态判定方式不再适用应以真实仓库的 CI 与评审流程为准。收尾时 notebook 会依次 archive session、environment、agent释放本次编排占用的资源wait_for_idle_status必须先于 archive 调用原因见 utilities.py 中该函数的说明SSE 流中的session.status_idle事件可能先于sessions.retrieve报告idle直接 archive 会收到 400。想对比单点修复场景可以回看 CMA_iterate_fix_failing_tests.ipynb它逐行演示了stream_until_end_turn内部封装的那个流式事件循环是 managed_agents/README.md 推荐的入口 notebook。【免费下载链接】claude-cookbooksA collection of notebooks/recipes showcasing some fun and effective ways of using Claude.项目地址: https://gitcode.com/GitHub_Trending/an/claude-cookbooks创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表