跳转至

网盘存量代码迁移实战:我们如何用三层架构管住 AI 的输出

Ch07.013 网盘存量代码迁移实战:我们如何用三层架构管住 AI 的输出

📊 Level ⭐⭐ | 17.6KB | entities/baidu-netdisk-kmp-migration-three-layer-agent-architecture.md

背景与动机

网盘主端积累大量存量代码,推进 KMP(Kotlin Multiplatform)多端复用过程中,核心挑战不是"能不能迁"而是"迁得稳不稳"。一个页面迁移涉及 UI 层、布局文件、业务逻辑和资源文件,依赖关系错综复杂。

直接让 AI 协助迁移后,项目组发现三个规律性问题:

  • 输出漂移:同一类操作,不同对话结果不一样——AI 每次重新理解任务,上下文略有变化输出就漂移
  • 后期幻觉:任务越复杂,加载文件越多,到后期 AI 开始生成"不存在的方法"
  • 串行瓶颈:UI、布局、业务逻辑本可并行处理,但只有一个对话窗口被迫串行

三层架构全貌

三层组合的职责划分如下:

层级 组件 解决的问题 适用场景
执行层 Skill 单点执行不稳定 具体执行动作
调度层 SubAgent 长链路上下文膨胀 有依赖需串行的步骤
协作层 Agent Team 多类型任务串行效率低 无强依赖可并行的任务

迁移流程分为两个大阶段:

  • 提取阶段:用 四路并行,把 UI、布局、业务逻辑、资源同时提取
  • 转化阶段:用 串行推进,按模块生成→资源转化→业务代码迁移→UI 转化顺序执行,步骤之间通过 Memory 传递关键产出

选型判断依据:任务之间有没有强依赖——有依赖需串行→SubAgent;无强依赖可并行→Agent Team;具体执行动作→Skill。

执行层 · Skill:解决输出不稳定

核心问题

AI 每次都在"重新理解"任务,上下文不同、表达方式略有差异,对任务的理解就不一样,输出自然不稳定。这不是模型问题,而是没有把"这件事怎么做"固化下来。

** 的本质**是把一类任务的执行方式写成可复用的规范文件,AI 调用时按规范走,不再每次重新理解。Skill 是无状态的,没有对话历史,只做一件事——被调用时稳定输出。

最有用的约束:Checklist

试过只写"你需要做什么"、试过写"参考以下示例",最后发现最有效的约束是 Checklist——把每个步骤拆成可以逐项打勾的检查项。AI 在多步骤任务里容易跳步,不是不会,是在执行序列里漏掉了某个环节。有了 Checklist,遗漏率明显下降。

另一个有效做法是分层管理文件:核心规则放主文件,边界情况和细节处理放 references 目录。Skill 文件一旦太长,AI 的注意力会分散,关键规则被稀释。

关键决策:提取→校验→修复 三层拆分

存量代码提取的难点在于力度控制——提少了依赖链路断,提多了包体膨胀。

一开始把提取和校验写在同一个 Skill 里,结果发现 AI 在"自己审查自己",天然倾向于认为结果没问题。后来把提取拆成三个独立 Skill:

  • extractor:以调用语句为入口扫描依赖,生成初始提取包
  • validator:独立校验提取结果,关注"还缺什么"而不是"提了什么"
  • fixer:只处理 validator 指出的缺口,定向补充

这个"提取→校验→修复"的三层结构后来在代码转化阶段也沿用了(converter → validator → fixer),证明这个拆分逻辑是通用的。

Skill 的价值不在于 AI 能做多难的事,而在于同一件事 AI 能做多稳。Skill 不是提前规划出来的,而是被真实错误倒逼出来的——某个场景反复出错、发现"这类问题每次都要纠正"时,就是需要固化成 Skill 的信号。

调度层 · SubAgent:上下文膨胀是必然问题

上下文膨胀的本质

在同一个对话里处理完整迁移流程,前期运行不错,但到了后期开始出现奇怪的错误——生成的代码引用了不存在的方法,资源 ID 映射关系对不上,前面刚讲过的约束后面就不管用了。

这是 上下文膨胀 的问题:当加载的文件超过一定量,AI 对早期信息的记忆开始模糊,用"看起来合理"的内容来填充被压缩的细节——这就是幻觉的来源,比输出明显错误更难处理。

** 的思路**:把长链路任务按步骤拆开,每个步骤交给一个独立的 SubAgent 处理,各自有完全隔离的上下文,互不干扰。

Agent-Memory:跨步骤信息传递

上下文隔离解决了膨胀,但带来了新问题:SubAgent 之间信息割裂,后续步骤不知道前序步骤做了什么。

解决方式是 ****:每个 SubAgent 完成工作后,把关键信息提炼成结构化文件存下来,下一个 SubAgent 启动时读取这份文件,在自己的独立上下文里继续推进。

Memory 文件不是对话记录的备份,而是"后续步骤需要什么"的提炼。如果只是把聊天记录原样存下来再读进去,上下文一样会膨胀。有效的做法是只提炼结构化的关键信息,比如资源映射表、模块结构配置、已确认的接口契约。

具体例子:资源转化(strings.xml、colors.xml 等)和 UI 转化是前后依赖的两个步骤。UI 代码大量引用资源 ID,如果 UI 转化的 SubAgent 不知道资源映射关系,就只能猜——这是幻觉的典型触发场景。实际做法:资源转化的 SubAgent 完成后,把资源 ID 映射表写入 Memory 文件;UI 转化的 SubAgent 启动时读取这份映射表,在自己的上下文里准确处理引用。

SubAgent 适合有前后依赖的串行流程。及早拆分任务,比等到幻觉出现再排查效率高很多。

协作层 · Agent Team:四路并行

并行效率

页面代码提取涉及四类文件:UI 组件、布局文件、业务逻辑、资源文件。这四类文件的提取逻辑完全不同,但彼此之间没有强依赖——布局提取不需要等 UI 提取完,资源提取也不需要等业务逻辑提取完。

如果串行处理,总耗时是四段的累加,而且单个 SubAgent 需要同时处理四类文件,上下文依然会膨胀,专注度也会分散。

** 的方式**:把四类提取任务分给四个专业 Teammate 并行执行,各自独立上下文,只关注自己负责的那类文件。

专注度提升的价值

各自只处理一类文件,上下文体积可控,对这类文件的依赖模式理解也更深——比如专注布局的 Teammate 对 include 嵌套引用的识别比"什么都做"的通用 Agent 准确很多。

并行的收益不只在速度上:分工带来的专注度提升,对任务质量的改善往往比缩短的时间更重要。

跨 Teammate 依赖:Mailbox 消息通道

四路并行并不是完全独立的。实际跑起来会遇到跨类型依赖:UI 提取 Teammate 发现代码里动态创建了一个 Dialog,需要通知布局提取 Teammate 补充这个 Dialog 的布局文件;业务逻辑里发现 API 调用引用了某个字符串资源,需要通知资源提取 Teammate 补充。

这类协调通过 Mailbox 消息通道实时处理,不需要等一个提取全部完成再补充,也不需要重新启动一轮。

核心经验

  1. Skill 是被真实错误倒逼出来的:规范很粗糙,在反复纠错里逐步补充边界条件和反例——把团队踩过的坑沉淀成了下次不会再踩的规则。
  2. 上下文膨胀的临界点比想象中早,漂移比崩溃更危险:幻觉出现时不是突然全错,而是逐渐偏离,每一步看起来都还好,到最后才发现方向不对。
  3. Memory 文件要提炼,不要备份:把对话历史原样传递没有意义,有效的是只传递"后续步骤需要消费的结构化信息"。
  4. 并行的收益不只在速度上:分工带来的专注度提升,对任务质量的改善往往比缩短的时间更重要。

深度分析

1. 三层架构揭示了 AI Agent 工程化的核心路径:从"用 AI 做事"到"让 AI 稳定地做事"

百度网盘项目从"直接让 AI 协助迁移"起步,到最终形成 Skill/SubAgent/Agent Team 三层体系,本质上是一次从"原型"到"产品"的工程化跃迁。初次使用 AI 时,团队关注的是"AI 能不能做这件事";但随着深入使用,核心问题变成了"AI 能不能稳定地、一致地、可重复地做这件事"。Skill 回答的是"怎么做才稳定",SubAgent 回答的是"长链路怎么调度才不失控",Agent Team 回答的是"并行任务怎么协作才高效"。三层不是堆叠关系,而是覆盖了 AI 工程化三个递进的层次——每一层解决的都是前一层无法覆盖的问题。

2. "提取→校验→修复"三层拆分是 AI Agent 工程中最有价值的反模式

这个三层拆分(extractor / validator / fixer)最反直觉的地方在于:它不是从任务逻辑推导出来的,而是从错误中被逼出来的。当把提取和校验放在同一个 Skill 里时,AI 天然倾向于"自己审查自己"——这是一个认知偏差,与人类代码审查中作者自审容易放过问题的现象完全一致。三层拆分的核心价值不只是准确性提升,更重要的是可调试性:每层独立,出问题时可以直接定位到是哪一层出了问题,而不需要在一个大的 Skill 里全部排查。这种"关注点分离"的思想在传统软件工程中常见,但在 AI Agent 实践中被验证有效,这是一个重要的工程经验沉淀。

3. 上下文膨胀是必然问题,不是偶发问题

项目组的一个重要认知是:上下文膨胀不是"运气不好遇到了",而是"任务长度必然会导致的"。这个结论基于一个简单的事实——LLM 的上下文窗口虽然有限,但在实际使用中,AI 对早期信息的记忆从很早的时候就开始衰减,不是因为达到窗口上限,而是因为信息密度随着新内容增加而被动稀释。这意味着"等到幻觉出现再排查"是一种被动且昂贵的策略——幻觉的特点是渐进偏离,不是突然崩溃,所以发现时往往已经走了很长的弯路。主动的任务拆分(在幻觉出现之前就拆开 SubAgent)才是根本解法。

4. Agent Team 的专注度收益是并行计算的特殊案例

Agent Team 四路并行的效果远超预期,原因是专注度分工带来的质量收益比时间节省更显著。这与传统并行计算(时间累加 → 时间并行)的逻辑不同:在 AI 任务中,单个 Agent 处理多类任务时,上下文会被多类任务的信息混杂稀释,导致对每类任务的模式识别深度都下降。而专一的 Agent 可以在自己的子任务上建立更深的对等模式理解(如专注布局的 Teammate 对 include 嵌套引用的识别精度)。这个发现对所有多任务 AI Agent 设计都有指导意义——并行不只是并发,它本身就是质量提升的手段。

5. Mailbox 消息通道是并行 Agent 协作的最小必要基础设施

四个 Teammate 并行执行时,跨类型依赖不可避免——UI 提取发现了 Dialog 需要布局文件,业务逻辑发现了字符串资源需要资源提取补充。如果为此重新串行化(等一个提取全部完成再补充),并行收益就清零了;如果重新启动一轮(整个任务重新跑),成本更高。Mailbox 消息通道的解法是:跨 Teammate 的协调不需要中央协调者,不需要重新启动,只需要一个异步消息队列让相关 Teammate 知道"需要补充什么"。这是分布式系统中常见的模式在 AI Agent 协作中的成功移植,说明 AI Agent 的协作层可以而且应该借鉴分布式系统的工程经验。

实践启示

  1. 从第一个 AI 项目开始就用 Skill 规范执行方式,不要等出错再补救:Skill 不是"高级用法",而是从一开始就需要的工程基础。关键是建立 Checklist 化的步骤拆解和核心规则与边界条件的文件分层——这些实践不需要很多成本,但会显著减少"同一类问题反复出错"的情况。Checklist 防止跳步,分层防止规则稀释,这两个简单约束组合起来效果显著。

  2. 用"提取→校验→修复"三层结构替代任何自包含的 AI 执行-校验逻辑:这条经验有通用性,不仅限于代码迁移。任何 AI 执行+AI 校验的场景都适用这个三层拆分原则——让 validator 视角完全独立于 extractor,不让执行者自己审查自己的产出。这个原则成本极低(只是把一个 Skill 拆成三个),但对输出质量的提升是本质性的。

  3. 在长链路任务中,及早识别 SubAgent 拆分点,不要等到幻觉出现:判断标准是"这个步骤的输入是否依赖上一个步骤的产出"——如果答案是 yes,就立刻拆成独立的 SubAgent。资源 ID 映射表写入 Memory 文件是一个典型场景:资源转化 SubAgent 完成后,如果 UI 转化 SubAgent 需要知道资源映射关系,就必须在 UI 转化开始前把映射表写入 Memory 并由 UI 转化 SubAgent 读取。这种"信息预传递"需要显式设计,不能依赖隐式的上下文记忆。

  4. 并行 Agent Team 的 Teammate 分工应基于"任务类型"而非"任务阶段":分工越细,专注度越高,质量越好。四路并行按文件类型(UI 组件/布局/业务逻辑/资源)分工,比按任务阶段分工能获得更深的专注度收益——每个 Teammate 只需要理解自己负责的那类文件的模式,不需要在多类文件之间切换上下文。这是并行 Agent Team 设计的核心原则。

  5. 为 Agent Team 配套 Mailbox 消息通道,并行执行才不会因为跨 Teammate 依赖而退化:当并行 Teammate 遇到需要其他 Teammate 补充的信息时,应该通过异步消息队列直接通知,而不是等本轮完成后再启动新一轮补充。Mailbox 消息通道是维持并行收益的必要基础设施——没有它,并行会因为跨依赖而逐渐退化到串行,但它的实现复杂度并不高,本质上就是一个异步消息队列。

原文存档