ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

128个AI Agent协作编码:从任务拆分到并发合入的工程实践

128个AI Agent协作编码:从任务拆分到并发合入的工程实践 AI coding Agent 工作流最近最热的话题已经从单个 Agent 能不能写代码变成了几十个甚至上百个 Agent 能不能同时在同一个代码库上协作。128 个 AI 智能体同时运行这是 Cursor 与 Baseten 对谈编码 Agent 下一步时最吸引人的数字之一。对多数团队来说这个数字背后的真正价值不是把 128 个 Agent 扔进仓库然后等待奇迹而是要先解决任务怎么拆分、并发怎么控制、结果怎么合入这三件事。这篇文章会围绕一个实际路线展开先理解多 Agent 编码工作流的基本形态再设计任务协议然后搭建一个最小并发执行器逐步扩容到 128 个 Agent最后处理运行中常见的超时、格式不稳定、代码冲突问题。适合正在建设 AI Coding 工具链的开发者、想引入 Agent 工作流的团队负责人以及准备把 Cursor 类 IDE 和 Baseten 类推理平台串起来的后端工程师。1. 先理解编码 Agent 工作流从单 Agent 到 128 个 Agent1.1 单 Agent 编码工作流的常见链路单个编码 Agent 的日常工作流可以简化成四步接收任务描述、读取相关代码、生成补丁或新文件、交给开发者审查。Cursor 这类 AI 编码工具就是把这条链路做进 IDE让开发者在编辑器中直接完成“自然语言到代码”的转换。单 Agent 的优点是好调试、成本低、结果容易控制。但它有两个明显限制。第一是上下文窗口有限。一个大项目可能有几十万行代码单个 Agent 不可能一次看完所有相关文件所以它只能依赖检索、索引或者开发者手动指定上下文。任务越大遗漏关键依赖的概率就越高。第二是迭代串行。一个 Agent 执行完一个任务后下一个任务才能开始。如果任务之间存在依赖关系串行没有问题但如果任务之间没有依赖串行就是在浪费模型推理资源和等待时间。1.2 多 Agent 为什么值得尝试多 Agent 的核心动机是并行。把一个大需求拆成多个可独立完成的工作项分给多个 Agent 同时处理理论上可以缩短整体时间。比如订单模块要改接口、改数据模型、改服务层、改测试这四个子任务如果改动范围不重叠并行处理就比一个 Agent 逐个完成要快得多。但多 Agent 不是越多越好。Agent 之间如果共享同一个代码仓库必然会出现文件冲突如果共享同一个模型服务又会出现请求排队和限流如果缺少统一的任务协议生成结果根本无法自动合入。所以 128 个 Agent 这个数量级本质上是在考验工程系统而不是考验模型能力。下表对比了三种常见规模对比项单 Agent小规模多 Agent8~32超大规模多 Agent128适用场景小功能、修 Bug、生成单文件模块重构、多文件并行修改大型代码库批量改造、分工协作主要优势便宜、易控、调试简单并行度适中冲突可控吞吐高能覆盖大量任务主要风险上下文不足、效率低任务拆分要求高、成本上升合并冲突、接口压力、成本失控需要的工程能力基本提示词工程任务编排、补丁合并并发控制、可观测性、自动评审从表格可以看出规模越大对工程能力的要求越高。128 个 Agent 并不是简单地把并发数从 8 改成 128而是要从任务设计开始就按大规模并行的标准来做。1.3 Cursor 与 Baseten 在其中的角色Cursor 和 Baseten 在多 Agent 工作流里处于不同层次。Cursor 是开发者的入口和评审界面。它适合编写 Agent 的任务定义、调试提示词、查看生成结果、处理代码审查。一个 Agent 生成的代码可以最终落到 Git 分支由开发者在 Cursor 中打开仓库、查看 diff、决定是否合入。把 Cursor 当成“人机协作层”更准确。Baseten 是模型推理和执行层。它的作用是部署代码生成模型提供稳定的 API 接口并承担 GPU 资源调度、自动扩容和请求负载。多 Agent 并行时每个 Agent 的“大脑”实际上是模型推理服务而不是 128 个独立运行的 IDE 实例。因此128 个 Agent 同时运行的架构更准确的理解是一个调度系统并发发起 128 个任务请求每个请求调用模型推理服务生成代码然后把结果收集回来做校验和合入。Cursor 负责开发体验Baseten 负责模型运行中间的工作流系统负责把两者连接起来。2. 同时跑 128 个 Agent 前先设计任务拆分和结果协议2.1 工作流编排模式串行、并行、混合多 Agent 工作流不是把所有任务一起扔出去。任务之间通常存在依赖关系例如先确定接口定义再实现服务层最后写测试。常见的编排模式有三种串行模式一个 Agent 完成后下一个 Agent 才开始。适合强依赖任务比如“先改数据库表结构再改 DAO”。并行模式多个无依赖任务同时执行。适合互不影响的模块比如“A 模块加接口B 模块修文档”。混合模式把任务组织成 DAG有向无环图有依赖的按阶段执行没有依赖的并行执行。这是生产环境最常用的模型。在设计工作流时不要一开始就追求 128 个 Agent而是先把任务依赖画清楚。一个任务执行完如果它的输出是另一个任务的输入那么这两个任务必须串行。反之如果两个任务只读同一个文件、不互相修改就可以并行。2.2 给每个 Agent 定义输入、输出和验收条件大规模并行的前提是任务能被机器解析。不能用“帮我优化订单模块”这种模糊描述因为每个 Agent 对“优化”的理解不一样结果就无法统一评估。一个完整的 Agent 任务定义至少需要以下字段任务 ID全局唯一用于追踪日志和结果。任务说明包含背景、目标、约束。目标文件Agent 允许修改哪些文件避免越界。依赖条件执行前必须满足的代码状态。验收条件如何判断任务成功例如“通过新增的单测”“不破坏已有用例”。输出格式补丁、文件内容还是 JSON 结构化结果。下面是一个 YAML 任务示例id: task-001 type: implement-service agent_role: backend_developer description: 在 user_service 中实现 getUserProfile 接口 target_files: - src/user_service/profile.py - tests/test_profile.py dependencies: - task-000 acceptance_criteria: - pytest tests/test_profile.py -q 全部通过 - 不允许修改 src/order_service/ 下的文件 output: format: unified_diff save_to: outputs/task-001.patch关键点是target_files和acceptance_criteria。target_files限制了 Agent 的操作边界避免并行任务互相踩脚。acceptance_criteria给后续自动评审提供了判断依据。2.3 从需求到任务拆分的示例以一个“订单系统重构”为例比较合理的拆分不是按代码目录硬切而是按“可独立验证的交付物”来切。任务组任务 ID内容依赖预期产物接口定义task-000定义订单查询接口 schema无接口定义文件数据模型task-001实现订单数据模型task-000模型代码服务实现task-002实现订单查询服务task-001服务代码单元测试task-003为订单查询服务写测试task-002测试文件数据库迁移task-004编写迁移 SQLtask-001迁移脚本文档更新task-005更新 API 文档task-003Markdown 文档task-003 依赖 task-002必须串行task-004 和 task-005 在满足依赖后可以和其他任务并行。任务拆分得好128 个 Agent 才有意义任务拆分得模糊Agent 越多越混乱。3. 搭建一个可运行的多 Agent 并发工作流3.1 环境准备下面这套方案使用 Python 作为编排层因为它的 asyncio、httpx、GitPython 等库可以快速实现并发调度和代码仓库操作。模型功能通过 Baseten 等推理平台提供的 API 调用不在本地运行大模型。准备清单如下依赖项说明Python 3.10支持 asyncio 和类型标注pip install httpx pyyaml gitpythonHTTP 调用、YAML 解析、Git 操作一个可调用的 LLM APIBaseten 上托管的代码生成模型需确认接口和认证方式Git 仓库用于保存任务补丁和分支任务定义文件使用上文 YAML 结构创建虚拟环境并安装依赖python3 -m venv .venv source .venv/bin/activate pip install httpx pyyaml gitpython这里要注意不同 API 平台的请求格式和认证方式可能不同。如果 Baseten 提供的 endpoint 兼容 OpenAI 的/v1/chat/completions格式可以直接用标准客户端如果不是需要封装一个统一的call_llm函数屏蔽差异。3.2 项目目录结构一个可维护的多 Agent 工作流项目目录结构应该把任务定义、调度代码、输出物和日志分开。agent-workflow/ ├── tasks/ │ ├── task-000.yaml │ ├── task-001.yaml │ └── ... ├── workflow/ │ ├── __init__.py │ ├── task.py │ ├── executor.py │ ├── llm_client.py │ └── merge_guard.py ├── outputs/ │ └── patches/ ├── logs/ │ └── workflow.log ├── run_workflow.py └── requirements.txttasks/放任务定义文件workflow/放调度代码outputs/patches/放 Agent 生成的结果logs/放运行日志。这样在排查问题时可以快速定位是任务配置问题、调度问题还是模型输出问题。3.3 用 asyncio 实现并发执行器核心调度器可以抽象成三部分任务队列、LLM 客户端、工作线程池。使用 asyncio.Semaphore 控制并发上限避免一瞬间打爆模型服务。下面是一个最小示例import asyncio import yaml from pathlib import Path from llm_client import call_llm async def execute_task(sem, task): async with sem: print(fstart {task[id]}) prompt build_prompt(task) response await call_llm(prompt) save_patch(task[id], response) return {task_id: task[id], status: done} async def run_workflow(task_paths, max_concurrency8): sem asyncio.Semaphore(max_concurrency) tasks [] for path in task_paths: task yaml.safe_load(Path(path).read_text()) tasks.append(asyncio.create_task(execute_task(sem, task))) return await asyncio.gather(*tasks) if __name__ __main__: results asyncio.run(run_workflow([tasks/task-000.yaml, tasks/task-001.yaml])) print(results)Semaphore 的作用是限制同时运行的协程数量。把max_concurrency设置为 128就相当于最多同时运行 128 个 Agent 请求。但这只是一个开始真正要考虑的是模型服务的吞吐能力和代码冲突问题。build_prompt必须把 YAML 任务字段转换成一个结构清晰的提示词尽量包含背景、目标、文件路径、约束和输出格式。输出格式最好要求模型返回标准 unified diff 或 JSON不要直接要求模型写整个文件因为 diff 更容易做冲突检测和合入。3.4 将 Cursor 接入工作流Cursor 在这一套工作流中的位置不是调度器而是“人机协作入口”。当多个 Agent 生成补丁之后开发者在 Cursor 中打开仓库逐个查看outputs/patches/下的 diff确认后再合并到主分支。可以让工作流把 Agent 输出整理成可评审的摘要例如cat outputs/summary.md摘要内容可以包含每个任务的状态、改动文件、测试结果和风险说明。开发者看完摘要后再决定哪些补丁要在 Cursor 中打开细看。Cursor 本身也可以承担“写任务拆分描述”的工作。开发者在 Cursor 里把需求拆成多个任务 YAML然后提交到配置仓库。这样Cursor 负责定义“做什么”工作流系统负责“怎么并行跑”Baseten 负责“模型推理”。3.5 将 Baseten 接入工作流Baseten 在这套架构里提供模型推理能力。一个典型的调用方式是在部署页拿到 endpoint URL 和 API Key然后在llm_client.py中统一封装。import httpx import os API_URL os.environ[BASETEN_API_URL] API_KEY os.environ[BASETEN_API_KEY] async def call_llm(prompt: str, timeout: float 30.0): headers { Authorization: fBearer {API_KEY}, Content-Type: application/json, } payload { messages: [{role: user, content: prompt}], temperature: 0.2, } async with httpx.AsyncClient(timeouttimeout) as client: resp await client.post(API_URL, headersheaders, jsonpayload) resp.raise_for_status() data resp.json() return data[choices][0][message][content]需要特别说明的是上面代码里的payload和响应结构是兼容 OpenAI 风格的示例。如果 Baseten endpoint 使用的是原生 SDK 或自定义接口这里的请求体和解析方式都要按实际文档调整。生产环境不能把 API Key 写在代码里要通过环境变量或密钥管理服务注入。timeout参数也不要写死应该按任务复杂度动态配置。4. 并发控制与结果合入128 个 Agent 不“打架”4.1 并发数不是越大越好128 的并发请求同时打向一个模型 endpoint如果 endpoint 本身的吞吐上限是 60 QPS多出来的 68 个请求就只能排队。排队本身不可怕可怕的是每个请求的超时时间设置不当导致任务集体超时然后触发大量重试进一步压垮服务。所以配置参数时要先确认模型服务的能力再决定并发数。常用策略是把并发数从 8 开始观察延迟和错误率再逐步调到 32、64、128。推荐参数表如下参数建议值影响初始并发数8验证任务拆分和响应格式最大并发数128提高吞吐但受 endpoint 限制请求超时30~120 秒太短易误判失败太长拖慢整体重试次数2~3避免瞬时抖动导致失败重试退避指数退避 1s/2s/4s防止重试风暴每次任务最大输出长度2000~4000 tokens防止超长输出拖慢解析和合入这里的核心原则是并发数、超时、重试必须一起调不能只调一项。4.2 隔离工作区与提交策略并行 Agent 最常出现的问题是多个 Agent 修改同一个文件。即使任务定义里写了target_files模型仍然可能“越界”或者在生成 patch 时带上不相关的改动。最稳妥的方式是给每个 Agent 一个独立的 Git 分支或独立工作区让它们基于同一个基线提交点工作。Git worktree 可以帮助在本地同时检出多个分支。git worktree add ../agent-task-001 -b agent/task-001 git worktree add ../agent-task-002 -b agent/task-002每个 Agent 在各自 worktree 里生成补丁工作流再把补丁统一收集到主仓库做合并验证。如果两个补丁修改了同一个文件合并时会冲突这时必须由开发者人工处理而不是让工作流自动覆盖。4.3 冲突检测与自动评审补丁合入主分支之前至少要做三层检查格式检查能不能被 Git apply 成功。静态检查是否通过了 lint、类型检查和已有单测。验收条件检查任务对应的测试用例是否通过。下面是一个简化版的合并守卫脚本from pathlib import Path import subprocess def apply_patch(patch_path: Path): result subprocess.run( [git, apply, --check, str(patch_path)], capture_outputTrue, textTrue ) if result.returncode ! 0: raise RuntimeError(fpatch rejected: {result.stderr}) subprocess.run([git, apply, str(patch_path)], checkTrue) def run_tests(): subprocess.run([pytest, -q], checkTrue) def merge_task(task_id, patch_path): apply_patch(patch_path) run_tests() print(f{task_id} merged)这个脚本强调“先检查再合入”。它可以作为 CI 流水线的一部分也可以作为工作流merge_guard模块被调用。4.4 运行与验证工作流入口文件run_workflow.py支持传入任务目录和并发数python run_workflow.py --tasks tasks/ --workers 128 --output-dir outputs/运行结束后可以查看汇总结果。下表是一个可能的输出示例task_idstatusduration_stokenspatchtask-000done12.31200outputs/patches/task-000.patchtask-001done18.61800outputs/patches/task-001.patchtask-002failed45.22100无有效输出task-003timeout60.00无验证成功不能只看状态码还要检查每个 patch 是否能合入、测试是否通过。如果大量任务 fail 或 timeout第一步不是增加并发而是回到任务拆分和模型接口配置。5. 从 8 个 Agent 到 128 个 Agent 的扩容路线5.1 先跑通最小闭环建议先用 8 个 Agent 跑一组无依赖的小任务把链路跑通。最小闭环包含任务定义、LLM 调用、补丁生成、合并守护、日志输出。这个阶段要验证三件事任务 YAML 能被正确解析落库或写入队列。模型能稳定返回可解析的补丁而不是半截 Markdown 或解释性文字。合并守卫能在补丁冲突时准确报错而不是静默覆盖。如果 8 个 Agent 时已经频繁出现响应格式不稳定那么 128 个 Agent 只会放大问题。5.2 逐步扩容并观察瓶颈从 8 到 128 并不是平均分配推荐按 8、16、32、64、128 逐步上调。每个阶段记录三个指标成功率完成状态的任务占比。平均用时从任务下发到补丁合入的时间。错误分布超时、格式解析失败、API 错误、合并冲突各自占比。并发数预期关注点典型瓶颈8任务拆分是否合理提示词质量32模型 endpoint 是否扛得住API 速率限制64补丁合并是否冲突文件边界定义128系统整体稳定性和成本并发、超时、成本如果某一步成功率开始下降先停止扩容排查对应瓶颈再继续。5.3 生产环境需要补的工程能力学习环境里一个 asyncio 脚本加一个 API Key 就够了。生产环境还需要额外关注配置、观测、安全和回滚。这里给一份可复用的生产环境检查清单配置外置任务配置、模型 endpoint、并发数、超时都从环境变量或配置中心读取。链路追踪每个任务都有trace_id贯穿日志、API 请求和补丁文件。观测指标记录成功数量、失败数量、耗时分位数、token 消耗、成本估算。限流与熔断model endpoint 返回 429 时工作流要自动降频而不是无限重试。权限隔离Agent 使用独立的 Git 账号推送代码需要走审批流程。回滚方案合入后的代码如果破坏构建可以快速 revert 对应任务分支。数据备份涉及数据库 schema 变更时迁移脚本必须可回滚。这些能力不一定要一次性全部做完但在设计阶段就要留出位置。6. 常见问题排查Agent 不响应、输出乱、合并冲突6.1 Agent 运行超时或 Execution Provider 无响应现象任务长时间处于 pending日志中出现类似the agent execution provider did not respond in time或read timeout的错误。可能原因模型 endpoint 并发已满请求排队。提示词过长模型生成时间超过客户端超时。网络抖动或 API 网关限流。重试策略配置错误导致大量请求叠加。检查方式先看模型服务的监控面板确认请求量、错误码和平均响应时间再看客户端日志确认超时设置和重试次数。解决思路调大单请求超时时间例如从 30 秒调到 90 秒。降低并发数避免请求排队。使用指数退避重试并在重试之间拉长间隔。确认任务信息量是否过大必要时把大任务拆成更小的子任务。预防建议不要在代码里写死超时从配置读取所有外部调用都设置timeout和retry。6.2 并发写同一个文件导致补丁丢失现象两个 Agent 的 patch 都能单独应用但合并后其中一个 Agent 的修改丢失或者 Git 冲突导致整个合入失败。可能原因任务拆分时没有严格划分target_files或者模型输出了定义文件之外的改动。检查方式在合并之前对比每个 patch 涉及的文件找出重叠项。解决思路增加脚本自动检测多个任务之间的文件重叠如果两个任务的目标文件集合有交集就让其中一个任务等待或者直接抛错。预防建议任务 YAML 中的target_files必须写清楚并作为提示词的一部分给 Agent。合入前必须执行git apply --check。6.3 Agent 输出格式不稳定现象模型返回的不是 unified diff而是解释文字、Markdown 代码块或者部分 JSON。可能原因提示词没有明确输出格式模型“自由发挥”了或者温度参数过高导致输出不稳定。检查方式查看原始响应内容确认是否包含预期的结构标记。解决思路在提示词中给出固定模板要求模型只输出 diff 内容设置temperature为 0.1~0.2增加一个解析函数能够从 Markdown 代码块中提取 diff。import re def extract_diff(raw: str) - str: match re.search(r(?:diff)?\n(.*?), raw, re.DOTALL) if match: return match.group(1).strip() if raw.strip().startswith(diff --git): return raw.strip() raise ValueError(no valid diff found)这个函数先尝试从代码块中提取再判断原始文本是否本身就是一个 diff。解析失败时不要直接丢弃要把原始响应保存到日志方便后续改进提示词。6.4 排查优先级表问题现象优先检查项常见处理任务全部超时API endpoint 健康状态、超时配置增加超时、降低并发、检查 API Key部分任务失败错误日志、失败 task_id按错误码分流处理输出无法解析原始响应内容、提示词格式统一输出模板、加解析容错补丁合并冲突多个 patch 的文件交集严格 target_files、人工评审成本飙升token 消耗、重试次数限制输出长度、减少无效重试7. 编码 Agent 的下一步从“生成代码”到“可验证交付”7.1 让 Agent 写测试和验收标准编码 Agent 下一步最重要的变化是从“生成代码”走向“生成可验证的交付物”。一个只输出代码的 Agent不能证明代码正确一个同时输出测试和验收记录的 Agent才能进入自动化评审链路。任务拆分的最后一环应该永远包含测试或验证动作。例如前端任务可以要求 Agent 输出组件代码和对应的组件测试后端任务可以要求 Agent 输出接口实现和集成测试。验收标准不是“能编译”而是“新增测试能通过且不影响已有用例”。7.2 Agent 之间如何传递信息128 个 Agent 如果完全没有信息沟通很容易重复造轮子。例如两个 Agent 同时实现同一个工具函数或者一个 Agent 修改了接口另一个 Agent 还在用旧接口。常用的传递机制有三种共享文件任务产物写入约定目录后续依赖任务读取。消息队列一个任务完成后把结果发布到队列下游任务订阅。共享数据库适合任务状态较多、需要长期追踪的场景。对编码 Agent 来说最实用的是文件加状态表。任务输出保存为文件状态表记录每个任务的完成状态和产物路径。依赖任务在执行前先检查上游任务状态如果未完成就等待或失败。7.3 组织协作团队 AI Coding 如何共同协作多 Agent 工作流最终要落到团队协作里。如果不设计人的角色128 个 Agent 生成的大量代码会变成新的技术债。一个可落地的人机协作流程是产品负责人写出需求开发负责人在 Cursor 中把需求拆成任务 YAML。工作流系统调度多个 Agent 并行生成代码和测试。开发者按摘要评审补丁重点看高风险任务。CI 流水线自动执行集成测试。合入主分支后人工抽查关键模块。这个流程的核心是“Agent 负责执行人负责定义和评审”。不要指望 Agent 自己决定做什么而要让它严格执行定义好的任务。7.4 下一步实践建议如果你正在搭建自己的 AI coding Agent 工作流建议按这条路径练习用一个真实小仓库手写 10 个任务 YAML先跑通单线程执行。改为 asyncio 并发设置 8 个并发观察输出和冲突。接入 Baseten 等推理平台统一封装 LLM 调用。加入补丁解析、合并守卫和测试检查。逐步把并发数提到 32、64、128记录每一步的指标。128 个 Agent 同时运行不是目的而是检验系统设计的一把尺子。能把 128 个 Agent 的结果安全合入并保证质量说明任务拆分、并发控制和自动评审这套工程链路已经成熟。对很多团队来说先用 16 个 Agent 跑高质量闭环比盲目上 128 个 Agent 更有实际价值。
返回列表