两年搭 Agent 的复盘:工程约束下的取舍

4 分钟阅读
·

本文是「Agent 开发实践与思考」系列第 20 篇。系列目录:

两年搭 Agent 的复盘:工程约束下的取舍

2024 年 7 月,我手写了第一个 Agent,核心是一百来行的ReAct循环(我手写了一个 Agent:从一问一答到”思考-行动-观察”循环)。当时要解决的是内部工具中单轮问答无法完成的任务,并没有计划写成系列。后来每遇到一个实际问题就记录一篇,21 个月后形成了 20 篇核心文章。2025 年 12 月的 AICoding 概念综述RAG 知识库调优 是系列之外的补充,不计入这 20 篇。

这篇不再把此前的做法归为“判断对”或“判断错”。提示词、上下文压缩、单 Agent、文件系统工作流,以及多 Agent,都是在特定工程条件下可用的补偿手段。它们解决的是当时模型能力、可接入的系统、风险边界、团队投入和交付周期共同造成的问题;条件变了,手段的必要性、成本和实现形态都会变。把某个手段写成长期原则,反而会掩盖当初为什么必须这样做。

先还原当时的约束

这一系列文章的时间跨度很长。早期模型在工具参数、长上下文和多步执行上的稳定性有限;内部系统的接口描述、权限和反馈链路也不完整;团队没有现成的评估基建,很多任务还要求在较短周期内交付。在这些条件下,工程的目标不是找出“正确的 Agent 架构”,而是在可接受的成本和风险内把任务完成。

因此我习惯从三个相互影响的部分排查问题:模型在当前任务上能稳定做出什么判断;运行时向它提供了哪些信息;它可以调用哪些工具,以及工具返回什么反馈。这只是排查入口,不是能力分类。一个错误通常同时跨越几部分。

例如Agent执行时出错。我先怀疑模型能力,调了两天提示词;调用日志显示,实际问题是工具的 date 参数没有写明格式,模型只能猜测,可能传“上周”,也可能传“2024年4月”。这里既有工具契约问题,也有模型可见信息不足的问题。补充参数描述后问题很快消失。这个经历让我保留了“先看轨迹,再决定改哪里”的习惯,但它并不意味着所有问题都能被分到某一个固定坐标。

把文章放回当时看,提示工程、记忆、RAG、压缩和 Skills 是在补足任务所需的信息;function calling、MCP、CLI 和代码执行是在接入可操作的系统;评估、测试和后训练提供了观察或改变行为的依据。每一项都可能随模型、接口和组织条件变化而迁移到别的层次,schema 同时是工具接口和上下文的一部分,评估也必须覆盖全部链路。

当时为什么要做这些事

用长提示词补足接口与流程信息

2024 年初,模型对隐含流程、业务术语和工具边界的掌握不够稳定,工具描述也不完整,所以我把操作步骤、异常处理和限制写进系统提示词,后来一度积累到几千行(系统提示词写到几千行之后:提示工程的整理术)。这不是因为提示词本身值得沉淀为核心资产,而是当时缺少更结构化、更可验证的承载方式。

模型升级后,原先为特定失误准备的补丁会失效,有时还会限制新模型的表现。现在更倾向于把稳定的业务规则放进工具契约、权限校验和测试,把任务所需的事实按需提供;提示词只保留角色、目标和能够明确判断的约束。若未来接口语义、运行环境和模型对齐能力更好,提示词还可以继续缩短。

管理上下文是为了控制噪声和成本

200K 窗口出现后,我曾以为大量历史可以直接保留。对当时的任务和模型组合而言,上下文接近 150K 后,模型对早期指令和关键信息的使用变得不稳定(长任务不失忆:上下文压缩、交接文档与子任务隔离)。压缩、交接文档和子任务隔离由此出现:它们让下一步只接触与当前决策相关的信息,也降低了推理成本。

这不是窗口大小的普遍阈值,也不能推出“长上下文一定无效”。它描述的是当时模型、任务和上下文内容的组合。更大的窗口、更可靠的检索和更好的状态管理都会改变取舍;只要无关历史仍会进入任务、调用成本仍需控制,筛选和组织信息就仍有工程价值。

先把单条执行链路做得可观察

2024 年中尝试多 Agent 时,Coordinator 负责拆分和汇总,其他 Agent 分别执行子任务。困难不在于无法拆分任务,而在于单 Agent 的输入、工具调用和结果都没有稳定的评估与追踪。一个 Agent 的错误被下游当成事实使用后,很难判断是任务拆分、上下文传递、工具调用还是某一步判断出了问题。今年 11 月才把这部分成本完整写出来([多 Agent 协作的真实收益与代价](../11-25-多 Agent 协作的真实收益与代价/))。

因此后来优先完善单条链路的 trace、失败样本和回归评估,再评估是否需要并行或角色分工。这是降低调试成本的顺序,不是说多 Agent 在能力上天然更差。任务足够独立、接口足够清晰、验证能自动化时,协作仍可能降低周期;反之,额外的交接与协调只会放大不确定性。

为风险和反馈补齐确定性

工具层承担权限与副作用控制

模型曾提出过看起来合理但危险的 rmforce push 等命令。提示词中的禁止语句会随上下文和任务变化失去约束力,也不能作为权限边界。因此目录白名单、参数校验、危险操作审批和可回滚设计放在工具层(拆解 Coding Agent:为什么”写代码 + 文件系统”是通用 Agent 的内核)。这样做的原因是副作用由系统控制,而不是依赖某次模型输出是否恰好遵守说明。

这类机制会随着系统的权限模型和工具能力演进,但只要 Agent 可以修改外部状态,执行前后的校验就需要由运行环境负责。模型能力提高会减少误调用,不能替代授权、审计和回滚。

评估用于替代主观判断

写完评估篇后(没有评估就没有迭代:我的 Agent 评估落地记),团队把主要改动放进评估集比较。此前改完提示词后凭体验判断效果,常在上线后才发现回归。评估集、trace 和失败 case 让我们能够比较版本,也能检查失败发生在检索、工具选择、参数构造还是结果处理。

评估不是开发流程的前置仪式。它只有在任务目标能定义、样本能维护、运行成本可承受时才值得投入。对一次性脚本或需求快速变化的任务,人工验收可能更合适;对需要持续迭代、切换模型或扩大覆盖面的任务,评估基建能降低重复试错的成本。

文件和代码用于外置状态与获得反馈

拆解 Coding AgentAgent 如何用代码完成推理、校验、适配与展示 中,我把文件系统和代码作为执行环境。今年的基建收敛项目再次采用了这条路径:团队把多套 Vue2、Vue3、React 基建收敛成一套,AI 编写约十万行代码,不到五天完成,我负责架构和验收标准(AI Agent First 驱动大型项目开发的经验复盘)。

这个项目需要长时间运行、频繁验证并允许人随时介入。文件系统使任务状态和中间产物可检查、可恢复,测试为修改提供反馈,所以它适合作为工作台。它不意味着所有 Agent 都应该围绕文件系统或 TDD 组织;对于结构化 API 流程、短事务或强约束工作流,状态机、数据库和专用编排系统可能更合适。

顺带提两篇系列之外的补充。AI Coding 概念综述梳理了 Prompt、Context、MCP、Skills 的发展脉络;RAG 知识库调优整理了知识库调优的工程细节,是 2024 年 RAG 补记的延续。

条件变化后,哪些取舍会改变

模型两年换了五六代,很多具体补偿已经在变轻:工具调用更稳定时,提示词中的格式补丁可以删除;长上下文利用更可靠、状态管理更成熟时,压缩策略可以调整;自动验证覆盖率提高后,任务可以拆得更细、并行得更多。此前的实践不构成一套不变的方法论,而是记录了这些能力尚未具备或成本尚未下降时的工程回应。

但有几类问题不会因为模型升级自动消失:模型仍然不了解私有系统和实时业务状态,外部信息需要以合适的形式提供;外部副作用仍需权限和审计约束;复杂任务的结果仍需要反馈来验证。这些不是对某种 Agent 形态的坚持,而是运行在真实系统中的输入、执行和验证要求。未来的实现可能不再叫 RAG、提示词工程或 Agent,但只要这些要求存在,系统仍要为它们分配责任。

我现在更在意的不是“哪条原则能穿越模型迭代”,而是每次条件变化后重新核算:当前的瓶颈在哪里,补偿手段的维护成本是多少,哪些责任可以交给模型,哪些必须留在系统里。

系列索引

按主题分组,新读者可以挑着看。

起点(手写循环与工具手艺):

喂给它什么信息(上下文主题):

它能动什么(工具与执行):

走向成熟(评估、学习与协作):

2026 继续观察什么

agentic RL 可能会提高环境和反馈设计的重要性。模型在环境中反复执行时,任务定义、奖励信号、验证器和成本约束都会直接影响训练或优化结果。这也会让评估基建从发布前检查逐渐变成运行环境的一部分,具体投入仍取决于任务是否需要持续优化。

Agent 之间的协议,例如 A2A,值得持续关注。当前多数场景的任务复杂度和系统边界还不足以证明专用协议的投入合理;当跨系统协作、身份传递、状态恢复和责任划分成为稳定需求时,再判断是否需要引入。

我希望把评估基建中可复用的部分从项目中抽出来,但能否推进仍取决于团队目标和实际需求。系列在这里结束,之后遇到新的约束、方案和结果,再单独记录。


614 字 · 83 段落
xi ming

Written by xi ming You should follow him on Github

评论与讨论