Deep Agents Monorepo 开发实战:基于 uv 与 make 的编辑-测试-lint 循环、Pre-commit 钩子与基准测试工程规范 📅 发布时间:2026/9/11 23:37:21 👁 浏览次数: Deep Agents Monorepo 开发实战基于 uv 与 make 的编辑-测试-lint 循环、Pre-commit 钩子与基准测试工程规范【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents本指南基于仓库 libs/DEVELOPMENT.md 展开它既是 Deep Agents monorepo 所有贡献者与开发者的第一入口文档也是理解libs/下多个独立版本包如何协同开发的路线图。读完你将掌握用uvmake完成从环境准备、依赖安装到单测/集成测试/lint/类型检查的完整开发闭环理解 pre-commit 钩子与分支命名校验的工作方式并能按仓库规范写出符合 Google 风格 docstring、正确抑制 ruff 规则、通过 warnings-as-errors 测试门槛的代码。这份文档解决什么问题libs/DEVELOPMENT.md是 Deep Agents monorepo 的开发起点文档面向两类读者需要改动某个包的贡献者以及想搞清楚每个包如何独立测试、发布、做基准测试的架构读者。它与 libs/ARCHITECTURE.md 分工明确后者讲运行时代码如何组织SDK 的三层结构、create_deep_agent()的组装与执行、中间件栈前者讲开发时如何动手改代码、跑测试、过 CI 门槛。仓库根目录的 AGENTS.md 则把这份文档作为全局开发准则的权威引用来源并在其中明确了Warnings are errors、per-file-ignores 使用策略、基准测试调用方式等细节的归属。文档的核心立场可以概括为三句话工具链只有两样uv管解释器、虚拟环境与依赖make管任务编排每个包的Makefile是命令的唯一事实来源。你只在正在改的那个包里工作不在根目录维护统一工程配置——monorepo 下没有根pyproject.toml。本地能过的检查要尽量覆盖 CI 会跑的检查format、lint、lockfile 新鲜度、Conventional Commit 消息、warnings-as-errors 测试。前置条件uv 与 make文档明确要求两个工具且态度很坚决uv负责解释器、虚拟环境和依赖管理。不要使用pip、poetry或conda。uv会自动按各包pyproject.toml的requires-python拉取合适的 Python 解释器因此没有需要全局安装或固定的 Python 版本。make任务运行器。每个包的Makefile是其命令的事实来源进入任意包目录运行make help即可列出全部可用目标。从源码看仓库在libs/Makefile中确实按包映射了 Python 版本libs/Makefile# Map package dirs to their required Python version # acp requires 3.14, everything else uses 3.12 python_version $(if $(filter acp,$1),3.14,3.12)也就是说仓库级命令会为libs/acp使用 Python 3.14其余包统一使用 3.12。而 SDK 包本身的requires-python范围更宽以 libs/deepagents/pyproject.toml 为例是3.11,4.0。两条规则叠加即可理解不固定全局 Python 版本、以包的声明为准的含义。仓库布局libs/ 下的独立版本包这是一个由独立版本管理的包组成的 monorepo所有包都在libs/下libs/ ├── deepagents/ # Core SDK — create_deep_agent, middleware, backends ├── acp/ # Agent Client Protocol integration ├── evals/ # Evaluation suite and Harbor integration ├── code/ # Prebuilt coding agent for interactive and headless use ├── talon/ # Local runtime host for long-running agents └── partners/ # Provider/sandbox integrations ├── daytona/ ├── modal/ ├── vercel/ ├── runloop/ └── quickjs/关键约定每个包都有自己的pyproject.toml、Makefile和README.md仓库根目录没有pyproject.toml。本地包依赖是**可编辑安装editable**的因此改了一个包依赖它的兄弟包在开发时立即可见新改动。包与包之间的横切约定Conventional Commits、分支命名、测试要求、公共接口稳定性统一收口在根目录 AGENTS.md并在文档中按子系统给出了精确的搜索路由例如 SDK 源码与测试在libs/deepagents/deepagents与libs/deepagents/tests避免在 monorepo 里做宽泛搜索。快速开始与 Setup文档给出的标准初始化流程在你要改的包内执行uv tool install pre-commit pre-commit install --install-hooks cd libs/deepagents uv sync --all-groups make test make lintuv sync --all-groups会安装包本身加全部依赖组test、lint 等。文档强调uv自动创建并管理虚拟环境不需要手动activate。monorepo 的四条铁律显式安装依赖始终用uv sync按需加--group name或--all-groups绝不允许隐式安装。不要在包目录之外创建虚拟环境。不要在同一个会话里混用多个环境。每个包在pyproject.toml里声明自己的 Python 支持范围不固定全局 Python 版本以包的requires-python为准。作为补充libs/code包还提供了一个一键引导目标make bootstraplibs/code/Makefile内部等价于uv sync --group test 回到仓库根执行uvx pre-commit install --install-hooks适合把整条开发链一次性配好。常用命令速查表在包目录如libs/deepagents内运行核心 SDK 包deepagents、code的命令一致其他包以make help输出为准命令作用make help列出该包可用的全部目标make test跑单元测试断网启用覆盖率的包会输出 coveragemake test TEST_FILEtests/unit_tests/test_foo.py只跑单个测试文件make integration_test跑集成测试允许联网make lint跑ruff检查 ty类型检查make format自动格式化并应用安全的ruff修复make type只跑ty类型检查器make coverage跑该包显式定义的覆盖率目标通常含 XML 输出也可以绕过 make 直接运行单个测试uv run --group test pytest tests/unit_tests/test_specific.py从 libs/deepagents/Makefile 可以看到这些目标的真实实现细节值得展开几点make test实际执行的是uv run --group test pytest -n auto -vvv --disable-socket --allow-unix-socket $(TEST_FILE) --benchmark-disable $(COV_ARGS)。-n auto来自 pytest-xdist 并行--disable-socket --allow-unix-socket来自 pytest-socket从机制上保证单测不能碰网络只允许 Unix socket。TEST_FILE ? tests/unit_tests/是默认值integration_test通过前置变量赋值把TEST_FILE切到tests/integration_tests/并加上--timeout 30防止联网测试挂死。lint目标 ruff checkruff format --diffmake typetype目标跑ty check deepagents。libs/code的lint还会额外校验命令目录generate_commands_catalog.py --check和工作目录约束check_process_cwd.py。仓库级命令从 libs/ 扇出在libs/目录下运行会扇出到所有包命令作用make lint逐个包执行 lintmake format逐个包执行格式化make lock更新所有 lockfile追加no-cache可绕过 uv 缓存make lock-check校验所有 lockfile 是否最新make lock-bump DEPpkg在所有 lockfile 中升级某个依赖以 libs/Makefile 的实现为证make lock会对所有发现到Makefile/pyproject.toml的包目录逐一执行uv lock --directory pkg --python versionmake lock-bump DEPrequests则对每个包执行uv lock -P requests。这意味着升级一个跨包依赖在仓库里是一条命令的事且始终带上与包对应的 Python 版本参数。DocstringsGoogle 风格 Args 段仓库要求每个公共函数都写 Google 风格 docstring规则定义在根目录 AGENTS.mdlibs/deepagents/pyproject.toml 中的[tool.ruff.lint.pydocstyle]配置convention google从工具层面强制了这一约定。文档给出了标准模板def send_email(to: str, msg: str, *, priority: str normal) - bool: Send an email to a recipient with specified priority. Any additional context about the function can go here. Args: to: The email address of the recipient. msg: The message body to send. priority: Email priority level. Returns: True if email was sent successfully, False otherwise. Raises: InvalidEmailError: If the email address format is invalid. SMTPConnectionError: If unable to connect to email server. 结合 AGENTS.md 的补充约定类型写在签名里而非 docstring 里不要重复默认值除非后处理或条件行为会改变它公共参数、返回值和异常要精炼描述重点讲为什么而不是复述代码函数尽量控制在 20 行以内。此外仓库强制ruff开启ALL全部规则见 pyproject.toml这意味着 pydocstyle 相关规则D 系列会在本地 lint 阶段直接拦截缺失或格式错误的 docstring。抑制 ruff 规则的正确姿势文档对这一主题的态度非常明确per-file-ignores是对整个文件生效的粗粒度开关只应为覆盖某一整类文件的原则性策略保留单条例外应该用行内# noqa精确到行、自文档化并在注释里说明理由——如果理由说不出来那大概率是代码本身有问题。文档给出的正反示例与 libs/deepagents/pyproject.toml 的真实配置相互印证# GOOD - categorical policy in pyproject.toml [tool.ruff.lint.per-file-ignores] tests/** [D1, S101] # BAD - single-line exception buried in pyproject.toml deepagents_code/agent.py [PLR2004]# GOOD - precise, self-documenting inline suppression timeout 30 # noqa: PLR2004 # default HTTP timeout, not arbitrary仓库实践中的两个典型类别策略tests/**放宽注解、docstring、魔法值、安全断言类规则D1、S101、PLR2004等见 pyproject.tomlscripts/**允许独立脚本使用盲捕获与print。这与 AGENTS.md 的全局约定完全一致不要把单条违规藏进文件级忽略里。Pre-commit 钩子与分支命名校验仓库使用pre-commit统一管理格式化、lint、lockfile 校验与 Conventional Commit 消息校验。安装方式uv tool install pre-commit # or: pipx install pre-commit pre-commit install --install-hooks从 .pre-commit-config.yaml 可以看到钩子的真实组成commit-msg 阶段conventional-pre-commit校验提交消息类型feat/fix/docs/chore等 13 种见 配置文件。pre-commit 阶段no-commit-to-branch禁止直接提交到maincheck-yaml、check-toml、end-of-file-fixer、trailing-whitespace等基础检查以及一组language: system的本地钩子按变更文件路径扇出到各包的make format lint如deepagents、deepagents-code、evals、acp见 .pre-commit-config.yaml。lockfile 与版本一致性钩子lock-check校验pyproject.toml/uv.lock是否同步、extras-sync校验 extras 与必需依赖一致、version-equality校验pyproject.toml与_version.py版本一致、branch-scopes-sync校验分支规则在钩子、CI、pr_lint 三处一致见 .pre-commit-config.yaml。pre-push 阶段branch-name钩子.pre-commit-config.yaml执行.githooks/pre-push。注意minimum_pre_commit_version: 3.2.0.pre-commit-config.yaml3.2.0 是第一个接受 git-hook 命名阶段pre-commit/pre-push/pre-merge-commit的版本更老的 pre-commit 会在 schema 校验阶段直接拒绝整个配置文件。分支命名 pre-push 钩子细节文档对分支命名校验的机制讲得很细核心事实pre-push 阶段拒绝不符合github-用户名/scope/短描述约定的分支例如mdrxy/cli/startup-cmd-flag。它通过 pre-commit 运行所以pre-commit install --install-hooks就会启用不需要单独配置core.hooksPath那会遮蔽其他已安装的钩子。如果你在钩子加入之前就装过 pre-commit必须重跑安装命令。pre-commit 在安装时按类型各写一个钩子文件老 checkout 的.git/hooks/pre-push不存在直到重装才会生效。钩子解析 GitHub 登录名的顺序是git config github.user→gh api user→user.email的本地部分。如果你的提交邮箱是users.noreply.github.com或first.last这类与登录名不匹配的地址显式配置是最可靠的做法git config github.user your-github-login永远放行的分支受保护分支main、master、vX.Y、自动化分支release-please--*、dependabot/*、copilot/*和发布分支alpha/*、beta/*、rc/*、dev/*。推这些分支时钩子根本不需要解析登录名。作为本地便利设施可用git push --no-verify或SKIPbranch-name git push跳过。两个盲区经由 pre-commit 而非裸 git 钩子运行的固有后果一次推送多个 ref 只校验其中一个推送没有新提交的分支不触发任何钩子。.github/workflows/branch_name_check.yml以 PR 头分支上的非阻塞警告覆盖这两点且 CI 故意不校验用户名段与 PR 作者是否一致——这一点上它比本地钩子更宽松。测试规范测试文件镜像源码布局deepagents/middleware/foo.py的测试放在tests/unit_tests/middleware/test_foo.pylibs/deepagents/tests/unit_tests/middleware 目录真实存在实测还覆盖了 backends、_api 等目录。测试原则见 AGENTS.md优先测真实行为、尽量少用 mock断网测试放tests/unit_tests/、联网测试放tests/integration_tests/不写只是复述实现结构的change-detector测试不手动加pytest.mark.asyncio因为各包都开了asyncio_mode auto。警告即失败Warnings fail the suite这是本仓库最值得注意的工程约束之一每个包都把error放在 pytestfilterwarnings的第一位任何仓库未显式接受的警告都会导致测试运行失败。规则出处是根目录 AGENTS.md实现见 libs/deepagents/pyproject.toml[tool.pytest.ini_options] filterwarnings [ error, ignore:Passing modelNone to create_deep_agent:DeprecationWarning, ignore:The feature forked subagents is in beta:langchain_core._api.LangChainBetaWarning, # ... ]error之后是按条目评审过的白名单。一个游离警告会以什么方式暴露取决于它何时被触发文档原话在测试内部触发该测试失败。在模块导入时触发该文件的收集collection失败。在 pytest 仍在配置阶段触发通常来自插件整个运行以INTERNALERROR中止——这是 CI 输出里最难读的一种。而且 pytest 加载插件期间、ini 过滤器生效之前发出的警告根本不会被捕获因此一次干净的运行并不能证明某个依赖是无警告的。应对策略先修可处理的警告把白名单条目当作最后手段。条目写法规则来自 AGENTS.md用pytest.mark.filterwarnings把预期警告限定到单个测试对PytestUnhandledThreadExceptionWarning之类倾向default::而非ignore::以保留可见性ini 里 message 字段是未转义的正则要转义字面元字符过滤器可以按版本限定如只在 Python 3.14 触发。bypass-warnings-check标签维护者可以对 PR 打上bypass-warnings-check标签并重跑失败任务从而把警告从错误降级。文档明确这是在时间压力下合入修复的逃生舱不是永久修复merge-queue 的运行会再次强制执行该策略警告最终仍必须被处理或加入白名单。它的两个边界只作用于走_test.yml的任务ci.yml里的test-quickjs-sdk-smoke任务直接调用 pytest没有绕过路径。发布运行release.yml始终强制执行因此只对构建出的 wheel 出现的警告无法靠标签放行。基准测试bench 与 bench-memory三个包承载基准测试libs/deepagents、libs/code、libs/partners/quickjs。每个定义bench墙钟时间与bench-memory堆内存两个 Make 目标其他包没有bench目标所以make -C libs/evals bench会直接失败。这些目标被视为基准测试调用的唯一事实来源本地运行和可复用 CI 工作流.github/workflows/_benchmark.yml都调用它们。要改基准测试的跑法改 Makefile 即可CI 自动继承。# 单包与 CI 调用的目标一致 make -C libs/deepagents bench # deepagents 与 code 一次跑完BENCH_PACKAGES 定义在 libs/Makefile # 注意不含 quickjs make -C libs bench-all # 不带 CodSpeed 插桩的纯 pytest-benchmark更快适合本地临时调优 make -C libs/deepagents benchmark以上命令与仓库实现完全对应BENCH_PACKAGES : deepagents code定义在 libs/Makefilebench-all目标在 libs/Makefile 扇出到这两个包libs/deepagents的 Makefile 中benchmark: ## Run benchmark tests uv run --group test pytest ./tests/benchmarks -m benchmark bench: ## Run benchmarks under CodSpeed instrumentation uv run --group test pytest ./tests/benchmarks -m benchmark --codspeed bench-memory: ## Run memory benchmarks under CodSpeed instrumentation uv run --group test pytest ./tests/benchmarks -m memory_benchmark --codspeed配套事实bench-memory只跑memory_benchmark标记的子集在 CI 中它由_benchmark.yml的has-memory-benchmarks输入门控默认false目前没有调用方开启所以内存基准实际上只在本地跑如果要在 sweep 中加一个就把这个 flag 接上。结果会上传到 CodSpeed 仪表盘每个包一个独立视图左上角选择器切换。回归阈值在仪表盘上管理不在仓库里文档明确提醒写在这里的数值会漂移写作时为全局 10%并建议对噪声底远低于该阈值的基准收紧逐基准阈值因为过宽的阈值会掩盖紧致代码里的真实回归。.github/workflows/_benchmark_nightly.yml是_benchmark.yml的唯一调用方没有 per-PR 基准任务。它按每日 cron 跑清单里的每个包保证未改动包的基线不漂移覆盖范围只有libs/deepagents和libs/code——libs/partners/quickjs虽然定义了基准目标但不在 sweep 里。在升级pytest-codspeed或CodSpeedHQ/action的 SHA 之前可用workflow_dispatch对该工作流做一次临时运行。贡献约定Conventional Commits 与 CI 门槛约定收口在根目录 AGENTS.md核心包括Conventional Commits 且必须带 scope、分支命名、测试要求与公共接口稳定性。规范的标题示例feat(sdk): add new chat completion feature fix(sdk): resolve type hinting issue chore(evals): update infrastructure dependencies test(code): missing unit tests for _git feat(code): --startup-cmd flag style(code): strip trailing annotations from ask_user questions补充约定来自 AGENTS.mdtype(scope):后以小写字母开头专有名词或命名代码实体除外类/函数/参数名用反引号包裹标题里不放 issue 关闭标记放 PR 正文版本分支同步用chore(repo): sync main into vX.Yrelease是类型不是 scope每个值得 bump 的 PR 只包含一个可发布组件跨包依赖或 lockfile 变动单独开chore(deps):PR。外部 PR 必须关联维护者已批准的 issue 或 discussion且贡献者需先被指派才能开 PR。CI 在测试之外还跑多项门槛Conventional Commit lint、lockfile 新鲜度、版本/extras 一致性、SDK-pin 检查等。在改动的包内跑make format lint、从libs/跑make lock-check即可清掉最常见的几项。与架构文档的衔接如果你要改的不是某个命令的配置而是 SDK 的运行机制文档建议先读 libs/ARCHITECTURE.md。它把系统切成三层来理解libs/ARCHITECTURE.mdLangGraph 是运行时state、checkpoint、streaming、interruptLangChain 的create_agent()是模型 工具 中间件组成 agent 循环的抽象Deep Agents 则是叠加其上的opinionated harness——通过create_deep_agent()组装默认中间件栈并配置 backends、subagents、skills、memory 与 profiles。开发流程上构造construction组装图与执行executionLangGraph 驱动循环是两个阶段而 harness 行为主要通过中间件注入。小结libs/DEVELOPMENT.md是进入 Deep Agents monorepo 的工程总纲通篇贯彻三条主线工具收敛uvmake拒绝 pip/poetry/conda 与根级工程配置、质量门槛前置warnings-as-errors、分支命名 pre-push 钩子、Conventional Commits、per-file-ignores 最小化、单一事实来源每个包的 Makefile 同时服务本地开发与 CI/基准工作流。按文档的顺序走一遍uv sync --all-groups→make test→make lint→pre-commit install --install-hooks你就能在一个可预测、可复现、与 CI 对齐的本地环境里完成对任意包的改动。进一步阅读运行时结构与 SDK 起点见 libs/ARCHITECTURE.md全局开发准则、测试要求与公共接口稳定性见 AGENTS.md仓库级扇出命令的实现见 libs/MakefileSDK 包内 lint/测试/基准的精确实现见 libs/deepagents/Makefile 与 libs/deepagents/pyproject.toml。【免费下载链接】deepagentsThe batteries-included agent harness.项目地址: https://gitcode.com/GitHub_Trending/de/deepagents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考