
adk-samples 的 prepare-python-recipe 技能八阶段流水线把 Python Recipe 一键调到 PR 就绪【免费下载链接】adk-samplesA collection of sample agents built with Agent Development Kit (ADK)项目地址: https://gitcode.com/GitHub_Trending/ad/adk-samplesprepare-python-recipe是 adk-samples 仓库中面向 Agent 的主编排Master Orchestration技能它把仓库内四个 Python Recipe 子技能generate-manifest、extract-python-environment-variables、align-recipe-pyproject、generate-python-runnability-test按固定顺序串成一条流水线对core/python/、contrib/python/或skills/vertical/solution/下已就位的 recipe 依次执行 manifest 生成、环境变量提取、pyproject 对齐、ruff 格式化、uv lock、runnability 测试生成与验证、仓库校验器终检共八个阶段。读完本文你将掌握这条流水线每一阶段做什么、为什么要按这个顺序执行、哪些环节必须停下来向用户确认以及如何读懂它输出的摘要表与 TODO 清单从而自己复现让任意 Python recipe 通过 python-validate-recipe.yml 全部检查的完整流程。技能定位交互式主编排而非又一个检查脚本该技能的定义明确它是master orchestration skill——Runs the other Python-recipe skills in the right order, with the right inputs, in a single pipeline见 SKILL.md。两个关键设计意图不重复子技能逻辑。凡是已有子技能或子技能底层脚本能做的事主技能一律委托给它们自己只负责排序、传参、判断结果与汇报。交互式设计interactive skill by design。它不只依赖 5 个固定检查点暂停而是允许 Agent 在任何阶段输出含糊、意外或需要人类判断时主动打断提问。触发场景包括runnability 生成器报告has_root_agent: false合法 recipe 永远应该为 true、manifest 推断出与你数到的 agent 数量不符的multi、环境变量一次性新增超过 10 个、uv lock记录到可疑依赖、recipe 出现非标准布局等。同时它刻意排除了部署化Dockerfile、fast_api_app.py、app_utils/等容器服务文件属于另一个可选技能make-python-recipe-deployable的职责绝不能在 prepare 流水线里未经询问地自动添加见 make-python-recipe-deployable/SKILL.md。前置条件必须在调用技能前手工完成技能假定用户已经完成以下手工准备SKILL.md 原文停用任何激活的 Python 虚拟环境在仓库根目录执行过git pull拉取最新代码在仓库根目录执行过uv sync同步根依赖recipe 已放置在目标路径——无论是新脚手架生成、从别处移动还是重命名为最终目录名位于core/python/name/、contrib/python/name/或skills/vertical/solution/下已提交原始 recipe使git diff能清晰展示技能做的改动。技能不会替你执行git pull、git commit、停用 venv 或移动/重命名目录——这些被刻意排除在范围之外。若用户未完成前置就要求运行应告知其先完成前置并停止。两个必须原样保留的规范占位符generate-manifest写入、tools/validate_manifest.py强制校验的占位符是精确字符串不允许发明、翻译或改写validate_manifest.pyOWNERSHIP_TEAM_PLACEHOLDER TODO: Replace with your team name OWNERSHIP_POC_PLACEHOLDER TODO: Replace with your GitHub user ID流水线中途绝不替换它们——这是刻意设计占位符保留到 CI 校验失败强制人类在合并前填上真实值。替换属于流水线结束后用户 TODO 清单What you still need to do的第一项。真实 recipe 的 manifest 中这两个字段被真实值填充后即为合法状态可参考 core/python/cross-session-memory/manifest.yaml。八阶段流水线总览技能对目标 recipe 依次运行八个有序阶段每阶段要么调用既有子技能或其底层脚本要么执行仓库标准命令阶段名称动作产出1Manifest缺失时生成manifest.yamlmanifest.yaml2Env vars提取环境变量到.env.example引导load_dotenv().env.example、__init__.py、pyproject.toml3Align对齐pyproject.toml与仓库标准pyproject.toml4Lintruff formatruff check --fix全部.py文件5Recipe lockuv lock --python 3.11uv.lock6Runnability test生成tests/test_runnability.py必要时附tests/conftest.py测试文件7Verifypy_compile pytest 运行验证结果8Validateuv run validate manifest/validate structure校验结论阶段 1Manifest先检查[ -f RECIPE_DIR/manifest.yaml ]若缺失通过skill工具加载generate-manifest技能并按其说明生成。该技能读取 manifest-schema.json 与 recipe 源码只推断代码能证明的字段typestandalone/module、deployable、large、architecture.agentsingle/multi按Agent(构造调用计数、architecture.stateful、architecture.datasources等并写入上述两个所有权占位符详见 generate-manifest/SKILL.md。若 manifest 已存在则跳过生成且不读取、不提示ownership.team/ownership.poc——无论里面是真实值还是占位符都保持原样。阶段 2环境变量提取直接调用脚本apply 模式不带--dry-runuv run --no-project python3 .agents/skills/extract-python-environment-variables/scripts/extract_env_vars.py \ --recipe-dir RECIPE_DIR必须用uv run --no-project python3而非裸python3脚本导入tomllib该标准库模块仅在 Python 3.11 存在uv 托管的解释器可保证版本。脚本会extract-python-environment-variables/SKILL.md将新发现的环境变量追加到.env.example含# extracted-by:extract-env-vars标记与溯源注释向包__init__.py注入load_dotenv()若缺失向[project].dependencies添加python-dotenv1.0.0若缺失把源码中硬编码的模型名字符串如gemini-3.5-flash改写为裸os.getenv(...)调用并在.env.example中记录替换。其底层有两条绝不打破的硬规则值得注意用户编辑安全——凡是无法证明是自己写入的.env.example行一律视为用户所有、永不修改分类器无法确定时失败关闭fail closedPython 文件只增不改——只允许三种写入load_dotenv()引导、尾随相对导入的# noqa: E402、硬编码模型字面量替换。阶段 3对齐 pyproject.toml —— 必须在阶段 4 之前这是全流水线最强调顺序的一环。对齐脚本会删除 recipe 本地的任何[tool.ruff*]表——删除之后 recipe 才使用根目录pyproject.toml的 ruff 配置。若先跑 lint就会按 recipe 自带通常更宽松的本地配置检查漏掉 CI 会抓到的违规导致流水线声称干净、CI 却失败。采用两遍逻辑先 dry-run 探测是否需要用户输入uv run --no-project --with tomlkit --with ruamel.yaml --with packaging \ python .agents/skills/align-recipe-pyproject/scripts/align_pyproject.py \ --recipe-dir RECIPE_DIR --dry-run解析 JSON若description-matches-manifest状态为needs_input需暂停展示pyproject_description与manifest_description请用户在pyproject/manifest/delete三选一。然后带或不带--description-sourceCHOICE执行 applyuv run --no-project --with tomlkit --with ruamel.yaml --with packaging \ python .agents/skills/align-recipe-pyproject/scripts/align_pyproject.py \ --recipe-dir RECIPE_DIR \ [--description-sourceCHOICE]对齐脚本共检查 8 条规则align-recipe-pyproject/SKILL.md 有完整表格规则 ID检查内容自动修复no-local-ruff-config不得声明任何[tool.ruff*]表是——删除python-version-floorrequires-python必须恰好接受 3.11既不允许更低如3.10也不得排除 3.11 如3.12是——重写下界为3.11并保留所有上界/排除/~上限/固定版本若结果仍排除 3.11 则拒绝并返回needs_inputproject-name-matches-folder[project].name必须等于 recipe 目录名skills/下为vertical-solution是——设置description-matches-manifest[project].description若设置必须等于manifest.description仅配合--description-source{pyproject,manifest,delete}build-system-present[build-system]须同时有requires与build-backend否——后端选择属编辑判断default-pypi-index[[tool.uv.index]]须有default true且指向公共 PyPIhttps://pypi.org/simple/整块缺失时是——追加已有默认条目但指向别处则否stale-python-version-refs扫描 recipe 内所有文本文件找出引用低于 3.11 下限的 Python 版本否——仅报告runnability-test-in-testpaths若设置了testpaths至少一项须能收集到tests/test_runnability.py否——仅报告关键退出码语义align 脚本只要存在report_only状态的检查如缺[build-system]、默认索引非公共 PyPI就以退出码1结束——这是设计内的延迟处理deferral-by-design不是硬错误不能套用规则 7 的 halt。应从 JSON 判断仅剩report_only就继续并把问题记入摘要只有error状态才 halt。四条会产生report_only的规则中build-system-present还有个连锁影响没有[build-system]的 recipe 永远不会被安装runnability 测试的import无法自行解析生成器会改而输出tests/conftest.py路径垫片path shim摘要中要把这两件事合并说明。阶段 4ruff —— 必须从仓库根目录运行uv run ruff format RECIPE_DIR uv run ruff check --fix RECIPE_DIR两条命令都从仓库根目录而非 recipe 目录运行确保根的 ruff 配置生效。ruff check的退出码需要区分对待退出码 1存在 ruff 无法自动修复的真实违规典型如C901复杂结构、PLR0912/0915分支/语句过多。不要停流水线记入摘要的 Manual TODO让用户重构或审核后加# noqa。退出码 2ruff 自身出错配置非法、文件系统问题或 ruff 缺陷不是违规计数——阶段 4 实际未执行按规则 7 视为硬错误停流水线并展示信息。另需注意E402与__init__.py的约定阶段 2 已在 recipe 包__init__.py的尾随相对导入from . import agent上压制E402——这是 ADK recipe 的规范模式load_dotenv()、os.environ.setdefault(...)等环境引导副作用有意放在from . import ...之前以保证 agent 子模块加载时环境变量已就绪。若阶段 4 输出中出现__init__.py的E402说明上游出了问题阶段 2 未识别该模式或阶段 2 与 4 之间出现了新文件。阶段 5recipe 级uv lock—— 为什么要显式--python 3.11pyproject 已稳定阶段 3 对齐、阶段 4 不触碰它此时重新生成 lockfileuv lock --python 3.11需在workdir RECIPE_DIR下执行通过工具调用的工作目录参数传递不用cd。两个关键理由为什么显式--python 3.11CI 的 python-dependency-policy.yml 在执行uv lock --check时固定 Python 3.11。若本地用机器上默认的解释器现代机器通常是 3.12lock本地干净通过、CI 却报出令人困惑的错误——工作流会把解释器不匹配误报为 lockfile is out of date。在流水线阶段强制 3.11 能把同样的不兼容提前到 pipeline 期暴露。阶段 3 的python-version-floor通常已重写过requires-python但显式 pin 仍能防御该检查过宽或 recipe 有兼容性上限无法降低的边缘情况。为什么是uv lock而非uv sync流水线的职责是准备 recipe不是安装并验证其运行环境。uv lock仅解析依赖并写入uv.lock——这正是 CI 与下游消费者需要的产物uv sync还会把所有 wheel 下载进.venv/既慢数分钟网络 I/O又可能以流水线无法干净汇报的方式失败C 扩展构建错误、网络抖动。用户审阅 diff 后自行uv sync获得真实.venv/。若 lock 失败则 halt 并原样展示错误。最常见原因是requires-python排除了 3.113.12、~3.12等且阶段 3 无法改写——修复方式是降低 floor 到3.11或 recipe 确实需要新特性时与维护者沟通更新 CI 的固定解释器。阶段 6runnability 测试生成[ -f RECIPE_DIR/tests/test_runnability.py ] echo exists || echo missing缺失时生成uv run --no-project python3 .agents/skills/generate-python-runnability-test/scripts/generate_runnability_test.py \ --recipe-dir RECIPE_DIR已存在时暂停询问用户保留现有默认或重新生成重新生成需追加--overwrite。若脚本因找不到agent.py而报错把信息展示给用户待其指明入口后以--agent-file path重跑——这是唯一一个有定义恢复路径的error情况。生成器generate-python-runnability-test/SKILL.md会安全遍历 recipe 找到最浅层agent.py用ast解析agent.py及每一个祖先包__init__.py检测导入期副作用vertexai.init(...)、google.auth.default()与环境变量读取扫描全树找INTEGRATION_TEST读取该约定是每个包的agent.py常在模块加载时调用位于别处的 helper只扫agent.py会漏然后生成两种形态的测试——无副作用时是极简形态有副作用时是受保护的guarded形态测试函数顶部setdefault环境变量with patch(...):块包住 import断言放在with块外。真实产物可参考 contrib/python/brand-search-optimization/tests/test_runnability.pyos.environ.setdefault(GOOGLE_CLOUD_PROJECT, test-project)后with patch(google.auth.default, return_value(MagicMock(), test-project)):包裹import brand_search_optimization.agent再断言root_agent is not None。生成器还会检查import_support导入能否解析的四种途径installable有[build-system]、pythonpath-ini有pythonpath [.]、existing-conftest已有根 conftest、generated-conftest技能写了tests/conftest.py路径垫片并把每个warnings原样转达。若conftest_action为skipped已有 conftest 未被覆盖说明垫片可能缺失需记入摘要的 Manual TODO。阶段 7验证编译 运行对生成或既有的tests/test_runnability.py做两级递进检查。测试设计为无副作用patch 掉vertexai.init与google.auth.default因此两步骤都不需要.env、ADC 或网络uv run --no-project python3 -m py_compile RECIPE_DIR/tests/test_runnability.py编译必须用uv run --no-project python3受保护的测试带多个 patch 时会输出带括号的with (...):块这是Python 3.10 语法在旧系统解释器下会报出虚假的SyntaxErroruv 托管解释器是 3.11因此这是真实的语法检查。uv run --no-project --with pytest pytest tests/test_runnability.py -q运行需workdir RECIPE_DIR使 pytest 的 rootdir 与用户自行运行测试时一致。为什么运行而不是--collect-onlypy_compile只解析import 无法解析的测试也能通过而--collect-only也不行——受保护形态把 import 放在测试函数内部、with patch(...)块之下收集阶段导入测试模块时根本不会触达 recipe 模块。只有真正运行测试才执行到 import。第三方ModuleNotFoundError在这里是预期而非发现阶段 5 只跑了uv lock没跑uv syncrecipe 依赖未安装。按错误中模块名分类模块名是依赖vertexai、google.adk、pandas→ 预期汇报deps not installed此结果对导入路径无结论性依赖失败先于 recipe 自身 import 触发应回退用阶段 6 的import_support字段回答该问题。模块名是 recipe自己的顶层模块阶段 6module_name的首段如scripts.agent中的scripts→ 真实发现导入路径损坏无论装什么测试都不会通过。六种结果及对应进度行情况判定进度行编译 0、测试通过passPhase 7 (verify): compile OK, test passes.编译 0、失败于依赖pass with notecompile OK; test not run (module not installed — run uv sync). Import path: import_support编译 0、失败于 recipe 自身模块failcompile OK but module is not importable.记 Manual TODO常见原因是缺[build-system]且无 conftest 垫片编译 0、断言失败root_agent is Nonefail真实 recipe 缺陷原样汇报编译非 0fail打印 stderr 到摘要作为 Manual TODO跳过 7c解析不过的文件无法运行不诊断、不重试、不自动修复文件缺失skipskipped (no tests/test_runnability.py to check).永远不要因阶段 7 而 halt 流水线——阶段 8 照跑、摘要照打。同时要诚实deps not installed意味着阶段 7 并未证明 recipe 能运行真正的确认在 Next steps 的手动uv sync uv run pytest。阶段 8仓库自有校验器终检最后运行是刻意保持薄的包装层检查逻辑都住在tools/与.github/policy.yml在此重实现任何一条都必然产生漂移。uv run validate manifest RECIPE_DIR uv run validate structure RECIPE_DIR两者都从仓库根目录以仓库根相对路径运行绝不用绝对路径两者失败时都非零退出但不套用规则 7 的 halt——阶段 8 是最后一步其失败是待汇报的发现而非崩溃。解读输出时区分两类失败所有权占位符失败是预期的ownership.team/ownership.poc仍持有规范占位符时校验器故意失败直到人类替换。摘要中汇报为expected并作为 TODO 清单第 1 项。其余都是真实发现缺必需文件/目录、超尺寸限制、schema 错误、命名违规——逐条原样列出并给出修复。若两个校验器的唯一失败正是两个所有权占位符recipe 即处于预期终态应直说而非当作失败展示。为什么阶段 8 存在历史教训流水线曾经在阶段 7 结束并报告干净运行而uv run validate structure却失败——recipe 通过了流水线建模的所有阶段仍被 CI 拒绝。典型例子是漏了tests/unit/目录。在技能内重实现策略检查必然产生漂移因此流水线把仓库自有校验器当作最终裁决者the repos own validators as the last word。阶段 0计划与确认总是最先做正式流水线之前还有四步前置检查这是本技能较新版本新增的防御层0a — 验证 recipe 目录真实存在[ -d RECIPE_DIR ] || { echo Recipe directory not found: RECIPE_DIR; exit 1; }路径拼写错误不应让用户白白走完计划确认往返后在阶段 1 才失败。不是目录则立即停止不展示计划、不提示。0b — 验证目录名符合 CI 命名规则。python-validate-recipe.yml的 Check 1 拒绝不匹配^[a-z][a-z-]*$或超过 .github/policy.ymlrecipe_naming.max_folder_name_length当前值 30的目录。历史上流水线对此盲目——会对data_science或MyBadName跑完全部阶段、报告成功让 CI 晚些时候拒绝 PR更糟的是阶段 3 的project-name-matches-folder会把坏名字传播进[project].name。用 check_folder_name.py 提前拦截MAX_LEN$(uv run --no-project --with pyyaml python3 .github/scripts/load_policy.py recipe_naming.max_folder_name_length) uv run --no-project python3 .agents/skills/prepare-python-recipe/scripts/check_folder_name.py \ --recipe-dir RECIPE_DIR --max-length $MAX_LEN该脚本纯标准库可被uv run --no-project python3调用合规时静默退出 0违规时退出 1 并列出具体违规字符、超长部分以及从当前名派生的建议合规名转小写、_→-、丢弃非法字符、按连字符边界截断。建议仅供参考——脚本绝不重命名任何东西并输出手工git mv命令。失败则在整个流水线开始前 HALT原样打印 stderr不展示计划、不提示继续、不问要我重命名吗——重命名目录是用户的决定他们手工改名后重新调用技能。0c — 对skills/下的 recipe 检查必需目录。.github/policy.yml 的required_dirs.by_root.skills为每个垂直技能强制固定形状scripts/、assets/、references/、tests/unit/。八个阶段都不会创建这些目录缺失者会活过整个流水线然后在阶段 8及 CI失败。core/与contrib/recipe 完全跳过此步两者required_dirs.by_root为空。这是信息性检查而非 halt空目录即满足检查而 git 无法提交空目录所以修复方式是.gitkeepmkdir -p RECIPE_DIR/tests/unit touch RECIPE_DIR/tests/unit/.gitkeep在 0d 的计划消息中提及缺失目录并提供创建选项用户同意才创建并记入摘要 Files created拒绝则转入最终 TODO 清单。不得未经询问就创建。0d — 展示计划并取得确认。先扫一眼 recipe 有无非标准情况包不叫app/、.env.example不在根、缺tests/、多余 Python 源码目录、AGENTS.md提到的弃用模型字面量影响流水线的要简要标注。然后以我在假设这些——如果哪条不成立请说明的方式展示假设已停用 venv、已在根目录git pulluv sync、recipe 已在目标路径并改好名再列出八阶段计划最后以 Nothing gets committed — youllgit diffat the end. Proceed? 结尾征求一个明确的 yes/no。用户说不就停止。Agent 规则什么时候停、什么时候继续九条规则定义了编排者的行为边界原文 SKILL.md 的 Rules for the Agent开场索要--recipe-dir八个阶段都作用于同一 recipe。开始前确认展示计划 目标路径取得一次性 go ahead此后除规则 5/6 外不再逐阶段询问。直接调用子技能脚本而非子技能自己的 agent 向 SKILL.md——因为子技能各有 want me to apply? 提示主编排模式下用户已对整个流水线 opt-in逐条提示是噪音。纯指令技能的例外generate-manifest无脚本只能通过skill工具加载其 SKILL.md 内联执行。固定检查点——此处必须暂停阶段 3 返回description-matches-manifest的needs_input→ 展示两侧文本请用户选pyproject/manifest/delete阶段 6 前若tests/test_runnability.py已存在 → 询问是否重新生成默认保留重新生成用--overwrite阶段 6 找不到入口点 → 展示信息并待用户指明后以--agent-file path重跑唯一有恢复路径的error子脚本标记的任何其他error→ 展示信息、停流水线、不重试。判断式打断——真正有帮助时才暂停出现意外检测如has_root_agent: false、manifest 推断与你计数不符、env 提取一次性新增 ≥ 10 个变量、align 的requires-python重写掉 README 声称支持的版本、uv lock记录可疑依赖、非标准布局、或正确答案依赖 recipe 之外的知识。不要为这些打断进度更新、装饰性好奇、以及答案不会改变下一步的只是想确认式提问。打断时要给出具体担忧、相关数据和明确选项而不是一句这看起来 OK 吗。硬错误 halt任何阶段脚本以非refused_overwrite的非零码退出就停止打印阶段名、错误与已做工作。阶段 3 例外align 只要存在report_only检查就以1退出——从 JSON 判断而非退出码只有error或意外的needs_input/would_fix才 halt。紧凑汇报每阶段一行Phase N (name): one-line outcome不倾倒 JSON、不重绘子技能表格判断式打断另起一轮提问、等答案。绝不提交摘要打印即技能完成git diff与 commit 交给用户。输入字段必填说明Recipe directory是recipe 根路径如core/python/cross-session-memory、contrib/python/my-recipe、skills/retail/store-ops作为--recipe-dir传给每个子脚本用户未指定时先询问再继续。收尾汇报格式摘要表、文件清单、未尽事项、TODO流水线运行中每阶段打一行进度同时跟踪三类信息供结尾汇报每个创建/修改的文件、每件尝试过但未完成的动作、每件需人工跟进的延迟项。结尾按四个板块输出第 3 节为条件性无内容则整节省略第 1、2、4 节总是输出。1. 摘要表八行阶段 / 结果 / 备注结果列用平实词ok/skipped/failed除非用户要求否则无 emoji。阶段 8 仅当唯一失败是两个所有权占位符时为ok这是预期终态而非缺陷。2. 创建或修改的文件分Created与Modified两组列短列表大组聚合如 12.pyfiles formatted (Phase 4)未触碰的省略。若什么都没改输出Nothing changed — the recipe was already fully aligned.3. 尝试但未完成的事有内容才打印halt 的阶段含命令与 stderr 片段、明确哪些阶段因此未运行、阶段 4 无法自动修复的 ruff 违规file:line — codes、阶段 6 conftest 垫片被跳过、阶段 7 编译失败或 recipe 自身模块 import 失败、阶段 8 除两个占位符外的真实校验发现。4. 你还需要做什么标准项总是列出① 打开manifest.yaml填入ownership.team/ownership.poc真实值CI 校验故意在占位符未替换前失败若 manifest 原本就有真实值则只是确认② 填写.env.example中每个TODO: ...占位符或删除未用变量行③cd RECIPE_DIR git diff审查所有改动后再提交。条件项仅当对应阶段提出时阶段 3build-system参考 align-recipe-pyproject/SKILL.md 中的 hatchling / uv_build 模板若阶段 6 已写 conftest 垫片补上 build-system 后垫片即冗余可删、pypi-index非公共 PyPI 需确认是否有意、stale-python-version-refs按可执行文件优先列出、testpaths需加tests、缺失必需目录补.gitkeep、其他校验发现逐条带修复。命令总是展示cd RECIPE_DIR uv sync # install deps into .venv/ (Phase 5 only ran uv lock) uv run pytest tests/test_runnability.py -v # confirm the runnability test actually passes # commit when youre happy最后停止不提交结束回合。从源码看这套流水线的工程价值从仓库证据可以总结出这套设计的三个核心工程判断策略不重实现、只委托八阶段中的检查逻辑manifest schema、pyproject 规则、命名/尺寸策略全部外置到 tools/validate_manifest.py、tools/validate_structure.py、.github/policy.yml 与 CI 工作流 python-validate-recipe.yml技能只做排序与裁决从根上避免策略漂移。把 CI 的坑提前到本地踩显式uv lock --python 3.11对齐 CI 固定解释器、阶段 0b 的目录名预检、阶段 8 的仓库校验器终检都是把PR 被 CI 拒绝的常见原因转化为流水线内可操作的提前失败。自动化与人的边界清晰占位符故意不替换、目录不重命名、不提交、不自动添加部署文件——自动化只做可证明安全的部分其余全部显式留给人工 TODO避免产生用户不想要的变更。【免费下载链接】adk-samplesA collection of sample agents built with Agent Development Kit (ADK)项目地址: https://gitcode.com/GitHub_Trending/ad/adk-samples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考