ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

跨平台AI编程智能体生态:架构设计与工程实践解析

跨平台AI编程智能体生态:架构设计与工程实践解析

这两年我一直在折腾 AI 编程工具,从最早的自动补全,到后来的对话式代码生成,再到现在的智能体(Agent)形态,前后经历了好几个阶段的迭代。说实话,前几种工具虽然也好用,但本质上还是“人在写代码,AI 在辅助”,直到接触了“Agency Agents”这类跨平台 AI 编程智能体生态,我才明显感觉到“换了个物种”——它不再是你写一句它补一句,而是像一个结对编程的同事,自己去读仓库、改文件、跑测试、查日志,然后告诉你“问题定位到了,代码改完了,测试也过了,你自己 Review 一下”。

这篇文章我会从架构设计和工程实践两个角度,把这套跨平台 AI 编程智能体生态的核心内容拆开来讲。包括为什么需要跨平台、Agent 的运行机制怎么设计、多智能体怎么协作、上下文和记忆怎么管理、沙箱安全怎么做,以及我在实际落地过程中踩过的一些坑和排查思路。不管你是想自己搭一套类似的智能体系统,还是打算把现有工作流接入 Agent 能力,这篇文章应该都能给你一些能直接拿来用的参考。

1. 项目动机与核心痛点拆解

1.1 为什么编程类 AI 一定要走向 Agent 形态

先聊一个很多人没细想的问题:为什么补全、对话生成这些偏“单轮交互”的形式不够用?

道理其实很简单。一个真实的软件开发任务,很少是“给我写一个排序函数”这种级别的需求。更多时候是“这个模块的内存占用一直在涨,帮我看看到底哪儿泄漏了”“把原来基于轮询的同步逻辑改成事件驱动,并且保持对外接口不变”“前端有个偶发的白屏问题,帮我从日志和代码两个方向一起查”。这些事情有几个共同特点:

  • 需要读取的上下文很长,可能要跨十几个文件、翻历史提交、看运行日志。
  • 任务不是一步到位,而是需要先探查、再假设、再验证、再修改,循环往复。
  • 每一步的结果都是不确定的,得根据中间输出动态调整下一步动作。

传统的对话式工具面对这类任务很容易“断片”,因为它的每个回答都基于用户手动喂进去的信息,AI 自己没法主动去仓库里刨根问底。Agent 形态则完全不同:它被赋予了调用工具的能力,可以执行搜索、读取、编辑、运行命令等动作,再根据工具的返回结果决定下一步。这样一来,“诊断问题”和“修复问题”这两件事就可以在同一个上下文里连续完成,而不是靠人来回搬运信息。

1.2 跨平台的本质需求

再说“跨平台”这三个字。很多人一听到跨平台,第一反应是“能在 Windows 和 macOS 上跑就行了”。但放在 AI 编程智能体这个语境里,跨平台的含义要更宽一些:

  • 操作系统层:开发者的本机环境可能是 macOS、Windows、Linux,甚至 Windows 下还有 Git Bash、WSL 等差异,智能体的 Shell 执行能力必须能适配这些环境差异。
  • 编辑器/IDE 层:有的团队全员 VS Code,有的团队用 JetBrains 全家桶,还有人习惯纯终端 + Vim/Neovim,智能体不能绑定在某一个编辑器上,否则推广起来阻力很大。
  • 语言与工具链层:Python、JavaScript、Go、Java、Rust 各自的构建工具、测试框架、包管理器完全不同,智能体的工具适配模块必须能识别不同项目的技术栈并调用对应的命令。
  • 运行环境层:本地开发、CI 流水线、远端容器,这些场景的操作权限、网络策略、可用的命令集都不一样。

如果只做一个“某个 IDE 里的插件”,那本质上还是一个工具,称不上生态。生态的意思是:同一套 Agent 核心能力,可以以不同的形态嵌入到不同环境里,并且保持行为一致。这个目标倒逼着架构上必须做“核心逻辑与运行环境解耦”的设计,也就是我后面要重点讲的适配层。

1.3 项目的目标用户与适用场景

从实际价值来说,这套智能体生态主要面向以下三类人和场景:

  • 独立开发者 / 小团队:在几个不同语言的项目之间切换,不想给每个项目都单独配置一套 AI 工具链,希望智能体开箱即用,自动识别项目结构和技术栈。
  • 中大型研发团队:内部有统一的代码规范、测试要求和 CI 流程,希望智能体不只会在本地改代码,还能在代码提交前自动做静态检查、跑测试、生成变更说明,把重复劳动消灭掉。
  • 对自动化有强烈诉求的进阶个人:比如写开源项目的人,希望智能体帮忙处理 issue 中的代码任务;或者搞技术研究的,想自己魔改 Agent 逻辑的人,需要的是一个可扩展的框架,而不是一个封闭的产品。

明确了用户和场景,架构设计的方向就清楚了:它必须是一个便于嵌入、可扩展、对外暴露清晰接口的开放体系,而不是一个功能堆叠、逻辑耦合的“大单体”。

2. 智能体生态的整体架构设计

2.1 分层架构总览

整个系统我按“接口层 - 调度层 - 核心引擎层 - 工具层 - 适配层”五个层次来组织,每一层只依赖下一层提供的稳定接口,不跨层调用。

  • 接口层(Interface Layer):对外提供统一的入口,包括 CLI 命令、IDE 插件(通过 LSP/DAP 等协议接入)、HTTP API 服务。这一层做的事情很薄,就是把各种入口的请求统一转换成内部的任务指令格式。
  • 调度层(Orchestration Layer):负责接收任务、拆解任务、编排多个 Agent 的协作流程、管理会话状态。它也负责调取记忆系统中的历史信息,决定当前的上下文要加载哪些内容。
  • 核心引擎层(Agent Core):这是智能体的大脑,包含推理循环、任务规划器、工具选择器、自我反思模块。它决定了“下一步做什么”以及“用什么工具做”。
  • 工具层(Tool Layer):定义了一批可被 Agent 调用的原子工具,比如文件读取、文件编辑、目录搜索、代码语义搜索、Shell 命令执行、Git 操作、测试运行等等。每个工具都有独立的输入输出协议和错误处理方式。
  • 适配层(Adapter Layer):负责把工具层的能力映射到具体环境中。比如 “execute_shell” 这个工具在 Windows 下走 cmd/PowerShell,在 Linux/macOS 下走 bash;又比如 “run_tests” 这个工具,会读取项目配置文件来判断用 pytest 还是 jest 还是 go test。

这样的分层设计最大的好处,是每一层都可以独立替换。比如你想换一个更强的底层模型,只需要改核心引擎层里模型调用的部分,接口层和工具层完全不受影响。再比如你想接入一个新的编辑器,只需要在接口层新增一个适配器,不需要动到 Agent 核心逻辑。

2.2 Agent 运行时:从“问答”到“行动循环”

Agent Core 里最核心的机制是“行动循环(Action Loop)”,这也是 Agent 与普通问答型 AI 最本质的区别。

一个完整的行动循环包括四步:

  1. 观察(Observation):从对话历史、工具返回结果、系统提示中收集当前状态信息。
  2. 决策(Planning):基于当前状态,生成下一步的计划,决定是继续分析、修改代码、还是向用户提问确认。
  3. 行动(Action):选择一个工具,构造输入参数,执行调用。
  4. 观察反馈(Feedback):拿到工具返回结果,更新状态,进入下一轮循环。

举个例子,用户给智能体提了一个任务:“这个项目跑测试的时候老是报KeyError,帮我查一下。” 智能体的循环可能是这样:

  • 第 1 轮:先搜索仓库里所有测试相关的文件,了解项目结构。
  • 第 2 轮:运行一次完整测试,复现报错信息。
  • 第 3 轮:根据堆栈中的文件路径和行号,读取对应源码,分析KeyError可能的来源。
  • 第 4 轮:修改代码,加入默认值或容错逻辑。
  • 第 5 轮:再次运行测试,验证修复是否生效。
  • 第 6 轮:把改动整理成 summary,并展示给用户。

这个循环看起来简单,但工程实现上有几个难点:每一轮的 token 消耗怎么控制、工具调用失败时怎么重试、循环最多跑多少轮防止死循环、遇到模糊场景时是继续猜还是停下来问人。这些细节我在后面“工程实践”部分会具体讲。

2.3 多智能体协作机制

单个 Agent 的能力再强,在一个复杂任务里很容易“顾头不顾腚”。比如既要改代码,又要保证代码风格统一,还要确保测试覆盖到位,一个 Agent 在同一个上下文里很难同时兼顾“执行者”和“审查者”两个角色,因为角色切换容易导致上下文混乱。

所以在架构里,我引入了“主从协作”模式:

  • 主控 Agent(Planner):负责理解任务、拆解步骤、分派子任务、汇总结果。
  • 执行 Agent(Worker):负责具体的代码修改、文件搜索、命令执行等操作。
  • 审查 Agent(Reviewer):负责检查执行结果,比如 diff 是否符合要求、有没有明显的 bug、测试是否真的通过了。

协作流程大概是:主控 Agent 先把一个大任务拆成若干个小任务,分给多个 Worker 并发执行,每个 Worker 执行完后把 diff 和自测结果交给 Reviewer,Reviewer 发现问题就打回给对应 Worker 重新修改。主控 Agent 最后汇总所有 sub-task 的结果,形成一个整体报告。

这个机制有几个好处:

  • 上下文隔离:每个 Worker 只需要关心自己负责的那部分文件,不需要把整个仓库的上下文都塞进同一个对话里。
  • 质量兜底:Reviewer 的存在能大幅减少模型“幻觉式改代码”的影响,相当于做了一个自动的代码评审。
  • 并行加速:多个独立任务可以并行执行,整体耗时比单 Agent 顺序执行要短不少。

不过多 Agent 协作也很容易踩坑,最典型的就是 Agent 之间互相打架:一个 Agent 改了文件 A,另一个 Agent 基于旧的缓存数据也改了文件 A,产生冲突;再就是反馈循环太长,Reviewer 不断打回,Worker 不断重改,来回好几轮都没收敛。这些问题我放到后面的问题排查章节里展开。

3. 核心工程实践与落地细节

3.1 上下文管理:给模型喂什么、不喂什么

这是我个人认为 Agent 工程里最考验功力的一部分,没有之一。模型的能力边界是固定的,但上下文窗口是有限的,怎么在有限的窗口里放最有效的信息,直接决定了 Agent 的表现。

我在实践中有几条经验:

  • 按需加载,不全量塞入:不要试图让 Agent 一次性读完整个仓库。比较可行的做法是先用目录树和关键词搜索定位到相关文件,再按需读取具体文件内容。比如一个典型的 Python 项目,我会先在src目录里做语义搜索,找出可能相关的模块,再读取这些模块的头部注释、函数定义和关键逻辑,控制单轮上下文在 30k~60k token 以内。
  • 分层压缩:对于一些比较大的文件,不要直接全文塞给模型。可以先提取这个文件的函数签名、类结构、核心逻辑片段,如果 Agent 在分析过程中发现需要看完整函数体,再单独读取“按行号区间加载文件”的内容。
  • 中间结果收敛:工具返回的结果往往非常长,比如grep -r "TODO" .可能返回几百行。这些结果不能直接全部塞进历史,而是需要做“收敛”处理——截断过长的列表、只保留匹配行和文件名、对重复信息做去重合并。
  • 历史裁剪策略:当对话轮次很多时,早期的对话内容可以逐步“摘要化”,比如把“用户最开始提出的需求 + Agent 已经完成的前三步动作”压缩成一段摘要,保留最重要的约束条件,释放窗口空间给新的工具结果。

补充一个参数上值得注意的常见经验:上下文占比尽量不超过窗口的 80%,因为工具返回结果往往带着格式标记,实际 token 消耗比预估的要大,留出余量能避免模型在关键步骤出现“截断式失忆”。

3.2 工具调用的协议设计与错误处理

工具层是 Agent 和外部世界交互的“手”。工具设计得好不好,直接影响 Agent 能不能稳定地完成任务。我在工具接口设计上总结了几个必须遵守的原则:

  1. 输入要严格结构化:不要用自然语言描述输入,而是用 JSON Schema 定义每个参数。比如file_edit工具就包含file_path、old_string、new_string、start_line、end_line等结构化字段,这样模型不容易乱填。
  2. 输出要带状态码:每个工具返回都应该包含status(success / error / partial)、output(主要结果)、error_message(如果失败)、metadata(比如耗时、行号信息),方便 Agent 判断是否重试或者换方案。
  3. 原子性优先:文件修改工具一次只处理一个文件里的一处改动,不要设计成“一次改十个文件”,否则定位失败原因会非常困难。
  4. 幂等性考虑:比如apply_patch这个工具,如果同一个 patch 被应用两次,第二次必须返回“no change”,不能报错也不能重复应用。

错误处理方面,我在实际调试中发现 Agent 在工具失败后经常犯同一个毛病——反复重试同一个操作,不换思路。所以我在调度层加了一条规则:同一个工具连续失败两次后,必须切换到“诊断模式”,即先执行env、ls、cat config之类的诊断命令,确认当前环境状态,再决定下一步,而不是盲目重试。

举一个很典型的例子:Agent 要运行pytest,结果返回了command not found: pytest。如果 Agent 靠盲目重试,永远不会好转;但如果它先运行which python、pip list | grep pytest,就会发现项目用的是虚拟环境,需要先激活 venv 再跑测试。这个“失败后主动诊断”的机制,能让 Agent 的工具调用成功率提升一大截。

3.3 适配层设计:同一套内核,适配所有环境

适配层的核心目标是让上层的 Agent 逻辑不关心底层环境差异,用统一的工具名和参数去描述动作,由适配层负责转换成具体环境中的执行指令。

以run_tests工具为例,适配层的工作流程是:

  1. 读取项目根目录的配置文件,识别项目类型。比如看到pyproject.toml或pytest.ini,判定为 Python 项目;看到package.json,判定为 Node.js 项目;看到go.mod,判定为 Go 项目。
  2. 根据项目类型选择测试命令模板。Python 项目用python -m pytest(优先)或python -m unittest;Node 项目用npm test或yarn test;Go 项目用go test -race ./...。
  3. 检查必要的环境依赖。如果pytest没装,适配层自动提示 Agent 先进入虚拟环境或安装依赖,而不是直接把裸的报错丢给模型。

再以execute_shell工具为例,适配层要做的事情更细:

  • 在 Windows 上,默认用cmd /c或powershell -Command执行,注意环境变量引用方式不一样(%VAR%vs$env:VAR)。
  • 在 Linux/macOS 上,默认用bash --noprofile --norc执行,避免用户自定义 shell 配置影响命令结果。
  • 对于路径分隔符、换行符差异,Agent 生成的命令通常基于统一接口描述(比如/home/user/project风格路径),适配层负责转换为系统实际路径。

这种设计还有一个额外的好处:当出现无法手动判断的项目类型时,适配层可以启动“探测模式”,依次尝试读取不同的配置文件,最后把探到的信息打包反馈给 Agent,让它自己决定采用哪种命令策略。

3.4 安全与权限沙箱

让 AI 智能体直接操作文件、执行命令,听起来是很爽,但风险也很实在。一个幻觉就能把配置文件的false改成true,一个莽撞的rm -rf就能清掉整个仓库。所以安全机制不能只停留在“代码审查”层面,必须从架构上做隔离。

我采用的安全方案分成四个等级:

  • 只读模式(L0):Agent 只能搜索和读取文件,不能编辑、不能执行命令。适合做代码审查、问题诊断。
  • 受限执行模式(L1):允许编辑文件,但只限当前工作目录;允许执行命令,但限制在项目目录内,并且禁止危险命令(比如rm、git push --force、chmod等需要额外确认的命令)。
  • 授权执行模式(L2):对于git commit、git push、依赖安装等需要外部副作用的操作,必须经过用户确认。实现方式是“命令预检 + 确认队列”,Agent 的执行请求会先挂起到前端,用户点确认后才真正执行。
  • 完全自动模式(L3):多用于 CI 场景,同时配合严格的命令白名单和执行日志审计。

实际操作中,我踩过的坑是:只做命令黑名单是防不住的。模型完全可以换一种方式表达危险操作,比如用 Python 的shutil.rmtree绕过rm命令。后来我把方案改成了“白名单 + 文件系统沙箱”,在 L1 模式下,所有文件写操作必须落在项目根目录白名单之外,Shell 命令必须匹配给定目录内的命令前缀,这样才基本堵住了常见的绕过思路。

4. 记忆与任务规划机制详解

4.1 会话记忆的分层设计

所谓“记忆”,不是把所有历史对话都堆在一起,而是分了三个层次:

  • 短期记忆(当前对话上下文):就是上面说的上下文管理里那一部分,负责承载当前任务的过程信息。
  • 工作记忆(任务级存储):针对一个具体的开发任务,保存这个任务的初始需求、已完成步骤、当前文件改动列表、待验证事项。这一层的存在,是为了让 Agent 在某个子步骤失败后可以“回退到最近的稳定状态”,而不是从零再来。
  • 长期记忆(跨会话知识库):保存 Agent 在这个仓库、这个团队中学到的经验。比如某个项目里,Agent 曾经发现修改消息队列的配置需要同时更新docker-compose.yml和.env.example,类似这样的经验会以“项目知识条目”的形式存下来,下次再处理相似任务时自动加载。

长期记忆的实现,我采用的是“结构化条目 + 标签索引”的方式,而不是纯向量检索。比如每一个知识条目会有三个字段:适用条件、操作要点、关联文件。当新任务到来时,系统会根据任务描述里的关键词和涉及文件路径,检索出最相关的知识条目,作为系统提示的一部分注入到上下文里。

4.2 任务拆解与执行循环中的参数控制

任务规划器的基本思路,是把一个大需求递归拆成“可验证的最小行动单元”。比如一个用户说“优化这个模块的并发性能”,规划器会拆成如下子任务:

  1. 分析当前模块的实现,定位并发瓶颈。
  2. 设计优化方案(至少要给出两个候选方案,并评估改动成本)。
  3. 实施改动,保持对外接口不变。
  4. 运行测试,确认性能提升且功能没有退化。
  5. 生成变更说明。

每个子任务在执行前,规划器都会先定义“完成条件(Definition of Done)”,这样在 Agent 执行完以后可以用自动验证来判定是否真的结束了,而不是模型说“做完了”就真的做完了。

执行循环里的几个关键参数,我贴一下自己项目里的默认配置作为参考(具体数值要根据模型能力和项目规模调整):

  • 最大迭代轮数限制:单个子任务最多执行 20 轮行动循环,超出则停止运行并向用户汇报中间结果。
  • 失败回溯深度:最多回溯最近 3 步,如果已经撤销了 3 轮操作仍然失败,就进入“人工介入模式”。
  • 计划修正频率:每执行 5 轮后强制做一次“计划复盘”,检查当前路径与最初计划是否偏差过大,必要时重新规划。

这些参数当初没什么“科学依据”,更多是根据实测调出来的。一开始我把最大迭代轮数设成 50,结果模型经常在有把握的任务上过度纠结,反复改无关变量;后来缩到 20,反而因为“必须尽快给结果”的压力,模型的决策更加果断,准确率还更高了。

5. 实际运行效果与实测对比

5.1 在纯代码生成任务上的表现

为了验证这套架构的真实效果,我做了一个简单的测试:在不人工干预的情况下,让 Agent 分别处理三个典型任务:写一个带有单元测试的 Python 工具函数、重构一个过长的 Go 函数、修复一个前端 JS 的偶发白屏问题。整体表现分成几个维度来看:

  • 成功率:三个任务里,前两个是一轮完成且测试通过的;第三个在经过 3 轮“运行测试 - 查日志 - 改代码”的循环后定位到了问题,属于异步渲染导致的事件绑定丢失,Agent 修完后测试也通过了。也就是说,三选三成,过程是 10~15 分钟不等。
  • 代码质量:生成的代码能通过 lint 检查,命名风格和项目现有代码一致(因为我在系统提示里注入了项目代码风格说明,并用 lint 结果作为反馈循环的一部分)。
  • 人工干预度:全程只做了一次确认(L2 模式下 git commit 前需要确认),其余完全自动化。

这个结果当然不算特别惊艳,但它证明了这套架构在“代码生成 + 验证反馈”这条链路是能跑通的。真正让它有价值的,不是“生成一段能跑的代码”,而是“在生成后自动验证、自动修正、直到满足条件”这个闭环。

5.2 在跨仓库/跨语言协作场景下的表现

第二个测试更贴近实际团队场景:我让同一个 Agent 实例处理三个不同技术栈的项目,每个项目都有独立的目录、独立的环境,用的是同一个智能体实例,只是切换了工作目录。

这个场景最能考验适配层的能力。实测下来:

  • 在 Python Django 项目里,Agent 能正确识别manage.py和虚拟环境,用python manage.py test跑测试。
  • 在 Node.js TypeScript 项目里,Agent 能自动读取package.json,用pnpm test执行测试,并且发现了tsconfig.json里strict模式导致的类型报错,顺手修掉了类型声明。
  • 在 Go 服务项目里,Agent 使用go test -race跑并发测试,并且通过go vet做了静态检查。

从用户体验看,切换项目时不需要任何额外配置,Agent 会在第一次进入仓库时花一点时间做“项目画像”:读取 README、配置文件、目录结构、关键代码文件的头部注释,然后把这些信息存入工作记忆,后续所有工具调用都基于这个画像来决策。

5.3 与传统 IDE 补全/对话工具的效率对比

最后再说说和传统工具的效率对比。我用同一个重构任务分别测试了一下:传统对话式工具需要我手动把涉及的几个文件片段复制给它看,然后它给出修改建议,我再去文件里手动改,改完还要自己跑测试确认。整个流程下来大约 30 分钟,其中一半时间花在“复制文件 - 粘贴代码 - 描述需求”这些体力活上。

而用 Agent 工具,我只需要在终端里输入一句话“帮忙把 X 接口的查询逻辑改成异步并保持行为一致”,然后就去干别的了。10 分钟以后回来,看到 Agent 已经改了 3 处文件、跑了测试、出了 diff,还留了一段变更说明。这种体验上的差距,比“补全准确率提高几个百分点”要本质得多——它把“让 AI 帮你写代码”变成了“让 AI 帮你完成一个开发任务”。

6. 常见问题与排查技巧实录

6.1 上下文溢出与 Agent“失忆”

这是我用 Agent 过程中遇到频率最高的一个问题。症状很典型:任务进行到一半,模型突然不记得最开始的需求约束了,或者连续做出和之前决策矛盾的改动。排查后发现,绝大多数情况是上下文窗口中塞进了太多工具返回结果,导致早期信息被“挤”出了窗口。

排查和解决思路:

  • 先看任务开始时的系统提示里,需求约束是否还在。如果只是短期记忆被挤掉了,可以人工提示 Agent “回顾一下你收到的第一个系统提示”。
  • 检查工具返回结果是否过大,尤其是 grep、search、test output 这类高输出量的工具,是否做了截断和收敛。
  • 检查历史摘要策略是否生效。如果大量早期内容还是原始全文,说明摘要压缩没有正常触发。

解决的方案我在前文 3.1 已经讲过了,核心就是做“分层摘要 + 按需加载 + 结果收敛”,这里不再重复。另外补充一点:实测中,把工具输出默认单次截断在 2000~4000 字符,对模型保持稳定推理非常有帮助。

6.2 工具调用死循环

第二个高频问题,是 Agent 在执行某个动作时不断重试,或者在两个工具之间来回切换,始终没有进展。比如 Agent 反复执行get_file_content和semantic_search,但搜索关键词始终不对,找不到想要的内容。

排查方法:

  • 打开执行日志,观察最近 10 轮的轮次记录,确认是不是在同一条路径上打转。
  • 检查工具输出是否包含“零结果”状态。很多时候 Agent 找不到文件,明明是因为搜索关键词和文件名偏离太大。
  • 手工介入,提示 Agent “停止当前搜索策略,改用全局文件列表扫描”,通常能跳出死循环。

我的架构里专门加了一个“循环检测模块”:当系统检测到最近 5 轮的动作类型重复度超过 80% 且没有文件变更时,会自动暂停 Agent,输出一条提示“检测到疑似循环,建议更换策略或请求人工协助”。这个机制在工程实践里帮我们避免了大量无效计算。

6.3 多智能体协作的冲突与反馈收不拢

多 Agent 协作模式下,最常见的冲突是“文件锁竞争”和“认知不一致”。文件锁竞争好理解,两个 Worker 同时修改同一个文件导致 diff 冲突;认知不一致是指主控 Agent 给两个 Worker 分配了看似独立但实际有依赖关系的子任务,导致两个 Worker 各自做出来的结果是互相矛盾的。

排查和解决思路:

  • 在调度层引入“文件级锁”:同一个文件在同一时间只允许一个 Worker 进行写操作,其他 Worker 如果想改这个文件,要么等待,要么以只读方式读取。
  • 任务规划时,主控 Agent 必须明确标注子任务之间的依赖关系,比如“子任务 B 必须等待子任务 A 完成后才能开始,因为 B 会修改 A 生成的文件”。
  • Reviewer 的工作是做“合并后检查”,而不是只对单个 Worker 的 diff 做检查。也就是说,要让审查者把所有 Worker 的改动合并到暂存区,跑一遍完整测试,再判定是否通过。

经历了多次“两个 Agent 各自都觉得没问题,一合起来就挂”的教训,我才痛下决心把合并验证作为审查的强制步骤。这个改变让多 Agent 协作的稳定性提升非常明显。

6.4 模型幻觉导致的“自信乱改”

最后说一个没法完全消除、只能抑制的问题——模型幻觉。具体到代码场景,就是 Agent 本来想修改文件 A,结果因为对某个函数的行为产生了错误理解,连带着改了文件 B、C、D,而且改得洋洋洒洒、异常自信。如果没有 Reviewer 机制,这种改动很容易被直接合入仓库,埋下定时炸弹。

抑制幻觉的措施,除了前面说的强制测试验证,还有几个实践中摸索的技巧:

  • 要求 Agent 在修改前先用git diff查看未暂存改动,用一个长长的上下文来“反复确认自己只改动哪些文件”。
  • 在系统提示里明示“如果你不确定某个函数的行为,请先搜索它的定义和调用处,而不是假设它的行为”。
  • 审查阶段用git diff --check检查空白错误,用 lint 工具检查明显的语法和类型问题,这些低成本验证能拦住大量 “AI 读了自己的输出就相信了自己”的情况。

我个人的态度是:模型幻觉消灭不掉,但工程机制能把它的影响范围限制住。只要修改能被测试捕获、被 Review 拦截,幻觉的代价就是可控的。

7. 一些实操心得与后续思路

最后聊聊我个人在这个过程中感受最深的两点,算是给打算做类似项目的朋友一点建议。

第一点是:Agent 的能力边界,很大程度上取决于工程细节,而不只是模型本身。很多人觉得“只要底层模型够强,Agent 就能干好活”,实际并不是这样。上下文管理、工具协议、错误重试策略、沙箱安全级别,这些看起来“不性感”的工程细节,才真正决定了 Agent 在复杂任务里的稳定性和可用性。我在调参过程中最深的感触是:一个设计良好的工具层,比一个更强的模型带来的提升更直接、更可控。

第二点是:要敢于给 Agent 设计“确认机制”。曾经我为了让 Agent 少打扰我,把所有权限都放到 L3 全自动模式,结果是它在一次会话里直接执行了git push --force,把远端历史给覆盖了。从那之后我才开始认真设计安全分级和确认队列。现在我的态度是:L2 授权模式应该作为默认,涉及副作用操作一律先确认,这种“慢”比 “出事故后回滚” 的“快”要快得多。

如果你对这套架构感兴趣,我觉得可以沿着几个方向继续扩展:把长期记忆做得更智能一些,比如自动从历史修复记录中挖掘知识条目;增强多 Agent 协作时的规划器,让任务拆解更精准;还有就是把沙箱安全做得更细,比如基于权限策略来控制 Agent 对敏感文件的访问。这个方向的技术演进才刚刚开始,后面应该还有不少值得玩的空间。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进