
最近两周我一直在折腾一件事用 Paseo 配合 Beads 搭一个软件开发的 Agent Team让它能在本地自动完成从需求解析、代码生成到代码审查的完整链路。目前第一版已经跑通了这两天把选型思路、架构设计和最小实现拆开整理一下。这个系列第一篇我不打算一上来就铺太多东西重点放在整体设计、环境搭建和一条最简流水线上先把地基打扎实后面聊测试闭环和 CI 接入才有得可说。先交代一下这套东西适合谁看你已经玩过一阵子大模型接口手头有一两个真实项目想让它参与开发但发现单次对话式的 AI 辅助效率不稳定、管不住上下文、更没法形成固定流程。这时候你需要的不再是一个会写代码的聊天窗口而是一套能分角色、按流程协作的智能体体系。下面我按自己的实操路径把每一步怎么想、怎么配、怎么踩坑都写清楚。1. 项目背景与整体设计思路1.1 为什么我会想搭一个智能体团队我平时要同时维护好几个小项目和几个工具脚本时间碎片化严重。真正消耗精力的往往不是写代码本身而是那些围着代码转的重复劳动读需求、拆分任务、写实现、自测、补文档、审代码。这些环节每个都不难但串起来很烦而且一个人干的时候标准还容易飘——今天心情好代码写得潦草也懒得回头改。一开始我也试过用一个 LLM 助手解决全部问题但很快就触到了天花板。单 Agent 有几个绕不开的毛病第一没有状态一次对话结束下一次它完全不记得之前的约束和结论第二没有分工同一个模型既写代码又审代码标准本质上是对着镜子自说自话第三没有产物管理它输出的东西是聊出来的不是沉淀下来的想追溯某次决策就得翻聊天记录。所以我把思路换了一下不追求一个全能的 Agent而是把它拆成一条流水线让不同的智能体各管一段前一个的输出明文落盘后一个拿来做输入。这就是 Agent Team 的基本模型。说白了有点像饭店后厨——切配的只负责切配掌勺的只负责炒传菜的只负责上流程固定下来之后哪怕换了个厨师菜的出品也不会差太多。软件开发也一样只要每个环节的输入输出契约固定质量就是可以被管理的。1.2 Paseo 和 Beads 分别解决什么问题这套方案里的两个核心工具我的定位是Paseo 负责编排Beads 负责任务拆解。Paseo 是一套流程编排工具解决的是谁先跑、谁并行、产物往哪传的问题。它把整个开发流程定义成一个有向无环图每个节点是一个可执行单元——可以是调用大模型的智能体角色也可以是一个普通脚本。节点之间的边决定了数据流向运行时会有一个共享上下文把各节点的产物串起来。我用它来定义需求解析之后才能开始开发代码完成后才能进入审查这类流程规则。Beads 则更像是任务库。我把一个大的开发任务拆成一串小的、边界清晰的原子任务每个任务都有独立的输入字段、输出字段、提示词模板和验收条件。它解决的是任务切多细、怎么验收、结果怎么缓存的问题。你可以把 Bead 理解成一颗珠子单独取出来能干活串起来能成链。这样做的最大好处是上下文干净每个模型调用只处理一个明确的小任务不会被无关信息干扰。选型的时候我也对比过其他方案下面这张表是我当时的真实权衡方案优点缺点全手工脚本加提示词灵活、无额外依赖维护成本极高流程一变就得改代码LangChain / CrewAI 等编排框架生态成熟、组件丰富抽象重、调试链路长学概念就要花不少时间Paseo Beads轻量、契约清晰、可本地跑生态相对小有些能力需要自己补齐最后选 Paseo Beads 的理由很简单我不需要那么多抽象概念我需要一个调度器加一份看得懂的任务清单。这两个工具的组合刚好落在够用和简单的交叉点上。需要说明的是Paseo 和 Beads 各自官方能力都不止我用的这部分我这里更多是站在编排器 任务库的定位上把它们组合起来用目前来看这个粒度对个人开发者最舒服。1.3 这个系列我打算怎么安排标题里标了一说明这是一个系列。我给自己规划了四篇节奏大概是第一篇是整体设计、环境搭建和最小可用流水线就是你现在看到的这篇第二篇做上下文压缩与多项目并行解决 Agent 在长任务中丢信息的问题第三篇接入测试反馈闭环和 CI让流程能跑在真实的 PR 场景里第四篇做效果评估用一组指标量化每个环节的产出质量。这个顺序不是随便排的。我自己的经验是先跑通一条最小链路再谈优化。很多人一上来就想要全自动闭环结果被各种边缘情况埋住最后连一个能用的版本都没跑出来。第一篇先把骨架立住后面每一篇都在这个骨架上加肉。2. 核心概念与角色模型拆解2.1 Paseo 的任务编排逻辑大模型本身没有任何流程意识它只会根据你给的提示词输出结果。所以编排层的职责就是替它记住现在进行到哪一步、下一步该干什么。Paseo 的编排模型我总结为三个核心概念节点、边、上下文。节点是执行单元可以是一个智能体角色也可以是一个脚本命令边定义了节点之间的依赖关系A 没跑完B 就不能启动上下文是一块共享黑板每个节点结束后可以把产物写进去后续节点按 key 读取。这个模型非常直白写配置的时候你不需要学习太多概念只需要想清楚数据从哪里来到哪里去。为什么我坚持用有向无环图而不是简单的顺序执行因为真实开发流程里有并行。比如代码完成后代码审查和文档生成可以同时进行——它们都依赖代码产出但互相不依赖。代码审查需要看 diff文档生成需要看接口注释两边可以各跑各的。如果只用顺序脚本这部分时间就被白白浪费了。Paseo 的图模型天然支持这种并行这也是我选它而不是手写 shell 脚本的重要原因。下面是我实际使用的一个编排骨架结构很清晰version: 1 name: demand-dev nodes: - id: parse type: bead bead: parse-requirement - id: implement type: bead bead: dev-implement inputs: requirement: {{ context.parse.output }}/requirement.md - id: review type: bead bead: review-check inputs: diff: {{ context.implement.output }}/changes.diff edges: - from: parse to: implement - from: implement to: review注意看 inputs 里的写法每个节点从 context 里取上一个节点的产物路径。这就是整个系统的关键——它不是靠模型自己记忆而是靠文件系统传递状态。节点间没有隐式对话只有显式数据依赖这样出了问题能定位跑重复了能缓存。2.2 Beads 的原子化任务拆分逻辑Beads 的核心思路是最小工作单元。每个 bead 只负责一件事内部包含完整的输入输出契约和验收条件。我维护的 beads 仓库里有十几个任务从解析需求到生成接口文档都有每个任务单独看都很简单但组合起来的可能性很多。为什么要拆得这么细三个原因。第一是上下文控制。一个 Agent 能有效处理的信息量是有限的你把整个项目的文件树、需求文档、历史代码全塞给它它反而分不清重点。拆成小任务后每个模型调用只聚焦一个明确的输入输出质量和稳定性都会有本质提升。第二是可缓存。Beads 的输入字段固定运行前会计算输入哈希。如果同一个任务的输入没有变化就直接复用上次的结果这一步能省下大量模型调用费用。我跑过一条流水线第二次运行时因为需求文档没改解析需求这个节点直接命中缓存整个流程只花了第一次的六成时间。第三是可组合。不同的项目可以复用同一串 beads只是参数不同。比如后端项目和前端项目都会用到代码审查这个 bead只是审查规范列表不一样。任务的复用性上来了新项目接入这套系统就只需要配置参数不用重写流程。每个 bead 的配置长这样id: parse-requirement name: 解析需求 input: raw_issue: string project_root: string output: requirement_doc: file acceptance_criteria: list[string] prompt: | 你是一名需求分析工程师... acceptance: - output 必须包含验收清单且条目不重复 - output 必须区分功能需求和非功能需求 max_tokens: 2000input 定义了任务需要什么output 定义了任务产出什么acceptance 是程序自动校验的兜底。我发现一个经验验收条件一定要写成可以被程序检查的句子而不是输出要高质量这种模糊表述。比如条目不重复可以检查必须包含验收清单可以检查但高质量没法检查。2.3 Agent 角色定义与协作模型我的 Agent Team 第一版定义了三个核心角色需求分析智能体、实现智能体、代码审查智能体。每个角色本质上是角色配置模板 Beads 任务的组合但各自有不同的行为约束。需求分析智能体负责把一句模糊的 issue 描述变成需求文档和验收清单。它最核心的要求是把不可验证的话翻译成可验证的条目。实现智能体负责写代码它的约束是只准动允许动的地方。代码审查智能体负责挑毛病它的核心要求是只针对变更范围做审查不跑题。协作流程我走的是线性链路用户提交 issue 描述 → 需求分析智能体产出需求文档 → 实现智能体根据需求文档产出代码 diff → 审查智能体拿 diff 与验收清单做对照输出审查意见。第一版没有做自动回滚和二次生成审查发现问题后由人工介入这是刻意做的减法——先把链路跑通再谈闭环。这里有一条贯穿全程的经验每个角色的输出都必须结构化。需求智能体输出 JSON 加 Markdown实现智能体输出 unified diff 格式审查智能体输出带严重级别的问题列表。结构化输出是这套系统能跑下去的前提散文式输出看起来有用但程序没法消费后续节点没法自动处理。3. 环境准备与基础工程搭建3.1 安装 Paseo 并初始化工作区先说环境。我在 Linux 服务器上跑这套系统Python 版本 3.11用 venv 隔离环境。安装过程不复杂两条命令的事python -m venv .agent-venv source .agent-venv/bin/activate pip install paseo-cli beads-cli装完后初始化一个独立工作区我建议不要直接在目标代码仓库里跑编排单独建一个目录作为调度中心paseo init --name dev-team --base-dir ~/agents/dev-team初始化后生成的目录结构是这样的dev-team/ flow/ # Paseo 编排文件 beads/ # Beads 任务定义 context/ # 运行上下文缓存 artifacts/ # 产物输出flow 放编排配置beads 放任务定义context 放运行时的中间状态artifacts 放最终的产物文件。刚开始我嫌麻烦所有东西都堆在根目录结果跑了几次之后目录乱成一锅粥找不到哪个文件是哪次流程产生的。分开之后清爽很多而且 git 管理起来也容易——beads 和 flow 要进版本库context 和 artifacts 要进 .gitignore。为什么坚持独立工作区而不是直接在项目里跑因为智能体产生的中间文件非常多需求文档、diff、审查报告、缓存这些都算是开发噪音不应该混进真实项目的提交历史里。工作区独立之后你想重跑流程或者清理缓存都很干净不会污染代码仓库。3.2 配置 Beads 仓库与依赖初始化完成后我把 Beads 仓库配起来。这个仓库本质上是一个任务库我要在里面维护所有可复用的原子任务cd ~/agents/dev-team beads init beads new parse-requirement --template role beads new dev-implement --template role beads new review-check --template role生成的全局配置文件 beads.yaml 里我统一管理模型参数而不是散落在各个任务里。这是我的习惯模型名、温度、超时时间这类全局配置只写一处换模型不用翻遍所有文件cache_dir: ./context/beads-cache default_model: qwen-plus default_temperature: 0.2 strict_output: truestrict_output 这个开关建议一直开着。它的作用是要求模型输出严格符合预期格式比如 JSON 就必须是合法 JSON不带 markdown 代码块包裹。第一次跑的时候我没开这个结果模型偶尔在 JSON 外面加了 json 标记解析直接报错排查了半天才找到是格式问题。开了 strict_output 之后这个坑基本就堵住了。模型服务地址按你实际使用的服务商填写各家差异不大关键是确认本地网络能正常访问。3.3 写下第一条最简流水线环境配置好后不要急着上真实项目先跑一条最小链路验证整个系统的连接是否正常。我用的是一个假需求用户登录时连续输错 5 次密码需要锁定账号 30 分钟这条需求足够简单又横跨了需求解析、实现、审查三个环节。编排文件就是 2.1 节那个 demand-dev.yaml。运行命令也简单paseo run demand-dev --issue 用户登录时连续输错5次密码需要锁定账号30分钟第一次跑的时候日志输出会非常直观每个节点都有状态标记[2025-01-15 14:03:22] nodeparse statusdone duration42s outputcontext/parse/output [2025-01-15 14:03:26] nodeimplement statusdone duration118s outputcontext/implement/output [2025-01-15 14:04:31] nodereview statusdone duration65s outputcontext/review/output看到三个节点都 done说明链路通了。这时候我会去 artifacts 目录手工检查每个节点的产物需求文档是否包含验收清单、代码 diff 是否可读、审查报告是否列出了具体问题。第一次跑通的标志不是没有报错而是每个节点产出的东西我都看得懂。如果某个节点的产物出现乱码、格式不对或者内容质量明显不行当场就要调整对应 bead 的提示词不要拖到后面。4. 三个核心 Agent 角色的定义细节4.1 需求分析 Agent把模糊需求变成可验收清单需求分析这个角色本质上是一名翻译官把产品语言翻译成技术语言再翻译成可验收的条目。它的核心难点不是理解需求而是防止模型写出提升用户体验优化加载速度这类无法验收的空话。我给它配置的温度是 0.1接近确定性输出。输出结构定义如下id: ba-agent role: 需求分析智能体 model: qwen-plus temperature: 0.1 output_schema: type: object properties: summary: string requirements: type: array items: type: object properties: id: string description: string priority: high | middle | low acceptance: type: array items: string在 prompt 里我特别加了一条硬性约束所有验收标准必须以可执行的动词开头例如当输入错误密码达到5次时系统应返回账号锁定提示禁止使用提高优化改善等不可验证的词汇。这条约束基本断绝了模型输出无效内容的路子。需求分析节点会产出两个文件一个是 JSON 格式的需求数据供后续节点程序化读取另一个是 Markdown 格式的需求文档供人阅读和确认。双产物设计是我特意保留的程序和人需要的格式不同没必要互相妥协。另外验收清单一定要和需求条目一一对应每条需求至少有一条验收标准这样才能保证后面的审查环节拿得到对照物。4.2 实现智能体限制范围才能不失控实现智能体是三个角色里最容易失控的一个。它拿到需求文档和项目上下文之后往往会太积极——顺手改掉测试文件、格式化整个目录、或者重构一段和本次需求无关的代码。这些都是我实际踩过的坑。所以我在角色定义里加了非常严格的范围约束id: dev-agent role: 实现智能体 model: qwen-plus temperature: 0.3 tools: - read_file - write_file constraints: allowed_paths: - src/** ignore_paths: - tests/** - docs/** max_file_changes: 10allowed_paths 声明了它只能动哪些目录ignore_paths 声明了绝对不能碰的目录max_file_changes 防止它一次改太多文件。配置之外prompt 里我明确要求它每次修改前先列出文件清单输出 unified diff 而不是直接覆写源码。diff 格式的好处很多人可以 review、机器可以自动应用、出了问题可以回滚。程序化应用 diff 的脚本我自己维护保证只把变更合入到目标文件里。还有一个控制手段是文件树限制。不要在上下文里塞整个项目的文件树那既费 token 又分散注意力。我只传两层目录结构外加几个关键文件的完整内容比如接口定义文件、配置模板。实现智能体需要的不是所有代码而是够理解本次变更的代码。这个度刚开始不好拿捏我建议从给关键文件 文件树摘要开始跑几次看效果再调。4.3 代码审查智能体用低温和清单保证标准统一审查智能体是最容易变老好人的角色。如果配置不当它会对有问题的代码说看起来不错。我把审查智能体的温度强行压到 0并且给它一份明确的审查对照清单命名是否清晰、异常分支是否处理、日志是否完整、是否满足验收清单每一条。输出结构强制定义成问题列表{ verdict: approve | request_changes, issues: [ { severity: blocker | major | minor, file: src/login.py, line: 87, message: 未处理验证码校验失败的数据库写入异常, suggestion: 补充 try-except 并返回明确错误码 } ], summary: ... }特别强调一条审查只针对 diff 范围内的变更。不加这句约束的话模型会开始评论整个文件的历史问题给你交上来一堆和本次需求无关的重构建议。我加了一条 prompt 规则如果某一处历史代码与本次变更无关请忽略你审查的唯一对象是本次提交的变更。效果立竿见影。还有一个细节审查智能体的输入必须包含原始的验收清单这是它做对照判断的依据。没有验收标准的审查就是拍脑袋模型只能凭感觉说看起来还行。把验收清单作为硬输入之后审查意见立刻具体了很多。5. 用真实需求跑通全流程5.1 场景选取给登录接口加验证码基础链路跑通后我换了一个更贴近真实开发的需求来验证给现有登录接口增加验证码校验。这条需求牵扯后端逻辑、前端交互、安全策略和数据存储恰好能检验并行编排的能力。我先把这条需求拆成了四个 Beads后端验证码生成与校验逻辑前端登录页接入验证码组件验证码过期与错误次数处理回归报告与代码审查每个 bead 都是独立的原子任务输入输出契约明确。比如后端的那个 bead输入是接口定义文件和需求文档输出是 diff前端的 bead 输入是页面组件文件输出也是 diff。前端和后端之间没有依赖关系所以它们可以并行执行。5.2 完整编排文件这个需求对应的编排文件比之前复杂一点因为引入了并行version: 1 name: dev-vcode nodes: - id: ba type: bead bead: parse-requirement - id: backend type: bead bead: dev-implement - id: frontend type: bead bead: dev-implement - id: review type: bead bead: review-check edges: - from: ba to: backend - from: ba to: frontend - from: backend to: review - from: frontend to: review执行顺序很清晰ba 完成之后backend 和 frontend 同时启动review 要等两者都完成后才能启动。这个图模型把并行能力用上了总耗时从串行的四段相加变成了ba max(backend, frontend) review明显比顺序执行快。我当时测试的结果串行从头跑到尾大约 6 分钟并行编排后 4 分半跑完省下来的时间全是后端和前端并行贡献的。对于小团队来说每次 PR 能省一两分钟都值得因为这是一天跑几十次的事。5.3 运行与检查跑完后artifacts 目录下会自动生成一次流程的完整快照flow/dev-vcode/run-20250115-1530/ context.json ba/output/requirement.md ba/output/requirement.json backend/output/changes.diff frontend/output/changes.diff review/output/review.json我会先看 review.json 里的 verdict如果是 request_changes就看 issues 列表里有没有 blocker 级别的问题。这次跑出来一个 major 级意见验证码校验失败时后端返回的错误信息过于详细有暴力破解风险提示。这个意见非常具体直接指向登录接口的安全策略问题说明审查 Agent 确实在按清单做对照。如果这时我想只重跑某个阶段不需要从头来一遍。Paseo 支持从指定节点重启paseo flow restart dev-vcode --from backend这个命令只重跑 backend 和它之后依赖 reviewba 的产物直接复用。配合 Beads 的缓存迭代速度会快很多。实际排查问题时从中间节点重跑的价值极大——你可以改了某个 Agent 的 prompt 后只验证这一个 Agent而不用每次都让全链路跑一遍。6. 踩坑记录与排查心得6.1 常见问题速查表这套系统跑了一周我把遇到的典型问题整理成了一张表基本覆盖了新手会碰到的绝大多数情况症状可能原因处理办法审查 Agent 几乎总是通过温度太高审查标准太松温度调到 0提示词里加入明确对照清单实现 Agent 改了不该改的文件白名单没有配置或者写错设置 allowed_paths并检查 ignore_paths 是否覆盖全输出 JSON 频繁解析失败模型输出夹带了 markdown 代码块打开 strict_output增加 JSON 修复重试逻辑某个节点结果没变但任务重跑Beads 缓存键没有覆盖全部输入检查输入哈希是否包含了验收条件和提示词版本日志里的中文变成乱码文件读写编码不一致统一所有节点用 UTF-8 编码读写文件流程跑很久但没有输出模型调用超时或者上下文过长调大超时时间对长文件做分段摘要再传给模型这张表不是一次形成的而是每次踩完坑就往里记一条。我建议你也维护一张类似的表因为这套系统只要跑起来永远会有意想不到的问题。6.2 我实际踩过的三个坑第一个坑是让实现 Agent 直接改仓库结果它把测试文件也改了。我最初没有配置 ignore_paths实现 Agent 拿到任务后顺手把测试文件里一个断言给改了逻辑看着没问题但测试修复和需求变更混在了一起交接给同事的时候解释了半天。后来改成先输出 diff由脚本按白名单应用变更彻底解决了这个问题。现在即使 Agent 动了测试文件diff 应用阶段也会被白名单挡住根本进不了源码。第二个坑是审查 Agent 太温柔。第一次跑时我用的是和实现 Agent 完全一样的模型参数结果连续三次流程都拿到 approve实在可疑。我手动查看代码明明有一个很明显的重复调用逻辑。问题出在温度和提示词上温度太高导致审查标准飘忽提示词里没有明确列出审查项它自然按猜的方式工作。把审查温度调到 0并在 prompt 里写明必须逐条对照验收清单每一条都要给结论之后审查意见的质量明显改善。第三个坑和缓存有关。我修改了一个 bead 的验收条件以为重新跑就会执行结果那个节点直接命中缓存跳过了用的还是旧逻辑的结果。排查后发现问题在于 Beads 缓存键的设计我只把输入字段作为哈希依据验收条件变更不会使缓存失效。解决办法是把提示词内容和验收条件一起纳入缓存键。现在每次改配置相关节点的缓存都会自动失效不会再用旧结果糊弄新逻辑。6.3 值得保留的调试习惯最后分享几条我每天调这玩意都离不开的习惯。第一每个节点的输入输出一律落盘不要只依赖终端打印。落盘之后的产物可以反复查看也能给后面的节点复用而终端日志滚一屏就没了。第二中间产物尽量用 diff 格式不要直接覆盖源文件。diff 可读、可审查、可摘除是天然的版本管理单位。第三维护一条冒烟测试链路。我有一条需求简单、耗时约三分钟的流程每次改完任何配置都先跑它确认链路没断再上复杂需求。这套系统越改越复杂没有快速验证手段的话一次失误可能要半小时才能发现。第四用 git 管理 beads 和 flow 的所有配置。我在最开始跑的时候吃过一次亏调了几个 Agent 的提示词之后发现效果反而变差了但因为没做版本管理找不回之前的配置。后来我把 beads、flow、prompt 模板全部纳入 git 仓库每次改配置都留 commit效果变差就用 git revert 回到上一个状态。这套系统的代码就是这些配置它们值得享受和源码一样的版本管理待遇。结尾搭建这套系统的过程中我最大的体会有两点。第一多智能体协作的真正难点不在模型调用而在任务边界和输入输出契约的划分——角色怎么定义、产物长什么样子、谁允许改哪些文件这些细节直接决定整个链路的上限。第二别迷信全自动关键环节保留人工监督是必要的。目前我的用法是让系统自动跑完一个流程但代码应用和最终合并始终由人确认Agent Team 做的是把脏活累活干掉而不是替代决策。下一篇我会把测试反馈闭环和 CI 接入补上配合自动化回归测试这套流程就能在真实项目的 PR 场景里持续运转了。