十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Agent技术债清理:从不可维护到可运维的实战路径

Agent技术债清理:从不可维护到可运维的实战路径 这个Agent现在还能加新工具吗 能但谁都不敢动。 为什么 因为没人知道改完其中某一段哪条链路会突然挂掉。上次我只是给一个工具的返回结果加了三个字段另一个流程的动作就全乱了。这不是我第一次听到类似的描述。最近这段时间从技术社区到朋友公司内部都能感受到同一个信号Agent项目过了最初的新鲜期之后普遍进入了同一个阶段——功能还在跑但代码已经变成一片没人敢踩的沼泽。调用链越拉越长prompt越叠越厚工具越挂越多真正决定行为逻辑的东西散落在各个模块里没人能说清。在我看Agent真正的问题不是“不够聪明”而是“不可维护”。而“不可维护”这件事正在催生一门很多人低估的生意——帮别人清理Agent堆积起来的技术债。这个话题我不想只停留在猎奇层面。我想聊清楚三件事Agent项目到底是怎么一步步变成“屎山”的为什么清理这堆东西在这个时间点特别有价值以及如果你手头就有一个跑得费劲的Agent系统可以从哪下手。1. Agent项目跑着跑着就成了没人敢碰的“屎山”1.1 症状不是“跑不动”而是“改不动”一个Agent系统如果已经运行过一段时间你不需要先去看代码。问三个问题就能判断它现在处于什么状态。第一个问题给Agent新增一个普通工具通常要改几个文件、改多少条prompt、影响几条已有链路如果答案是需要小心地翻半天代码再顺手把好几段prompt都改一遍那说明它已经没有清晰的边界了。第二个问题某次模型升级之后有没有哪个流程的输出格式悄悄变了但没有被任何人及时发现这个问题问到点上大多数人都会愣一下。因为Agent的行为不完全由代码决定模型一换很多原本被prompt压住的“自由发挥”就会重新冒出来。第三个问题当一次Agent执行中途失败时团队能不能精确回答“它已经执行到哪一步、调用过哪几个工具、用了多少上下文、失败在哪一层”如果报错之后只能靠猜那说明观测能力基本为零。最近看到有人在搜那个“agent execution provider did not respond in time”和“agent execution terminated due to error”的报错。这些报错本身并不算罕见真正麻烦的是团队面对它们的时候没有后续手段不知道失败是偶发还是必然是上下文太长还是工具无响应是模型服务不稳定还是Agent自己的设计缺陷。没有这些信息大家就只能一遍遍重试赌运气。1.2 为什么Agent比传统老项目更容易积累垃圾传统Web项目和Agent项目最大的区别不是语言或框架而是“动作主体”变了。传统项目里最终行为基本由代码决定输入进函数函数按逻辑返回结果你可以在任意位置打断点也可以断言输出的每一个字段。Agent项目里很多行为由模型决定而模型对同样的输入可能给出不同的解释和执行路径。模型版本升级、温度参数调高、上下文内容变化都会让行为产生偏移。这会带来一个很实际的结果传统项目里的“重构”手段放到Agent项目里不一定成立。传统项目里你可以把一段重复代码抽成公共函数只要输入输出不变外部行为基本不变。但在Agent项目里把一段prompt从A模块挪到B模块模型行为可能就完全变了。因为prompt的位置、上下文的前后顺序、甚至分隔符都可能改变模型对任务的优先级理解。另一个原因更加隐蔽Agent开发的“快捷方式”特别容易变成债务。功能表现不好开发者的第一反应往往是——给prompt加一句约束、给Agent多挂一个工具、在返回结果里再做一层修正。这些方式短期见效快几乎没有什么接入门槛于是它们不断在项目里累积。三个月之后你会得到一份超长prompt、十几个注册了但很少被调用的工具、四五层互相叠加的输出修正逻辑。每一层单看都有道理叠在一起就没人敢动了。所以给Agent清理“屎山”这件事本质不是把代码写得好看而是给一团没有边界的行为重新画清楚边界。2. 先弄清楚Agent“屎山”到底是哪几层脏想把Agent清理好第一步不是动手重构而是先承认“脏”不是一种模糊感觉。它通常体现在三个具体技术层上。2.1 第一层Prompt 越长行为越玄学很多Agent项目的问题写在看起来最无害的地方——prompt。最典型的状态是某个Agent的system prompt已经积累到几千字里面包含角色设定、业务规则、输出格式、若干条“注意”“非常重要”“禁止”之类的强调甚至还有上一位同事加的“当不确定时请按以下方式处理”的兜底说明。这种超长prompt最大的麻烦不是token成本而是不可观测。你删掉其中一句提醒模型行为不一定变差可能反而变好了你增加一句新规则原本稳定的输出格式反而乱了。因为模型对指令的理解不是线性叠加的它会把整个上下文组合出语义优先级。你根本不知道哪条规则真正生效哪条规则已经被后面的内容覆盖哪条规则在多个Agent之间共享着——改A的时候B和C也被动变了。很多团队在不知不觉中把prompt写成了“项目文档”所有历史规则都保留所有尝试过的约束都堆上去。这个习惯放在代码里勉强能接受放在prompt里就是在制造不可维护性。真正需要的是把prompt做分层角色定义、场景说明、功能约束、输出格式每一层独立成块每一块只负责一件事任何改动都配得上一次回归验证。2.2 第二层工具、记忆、编排逻辑全搅在一起Agent系统通常由几个不同能力构成会调用外部接口的工具、会读写历史信息的记忆、决定调用顺序和结束条件的编排逻辑。理论上它们是三个独立模块。但实际项目里我经常看到它们被写成了一团工具函数里塞了业务规则同一个工具在不同链路里的返回格式还不统一记忆被无差别写入大量临时信息、中间思考、失败尝试都留在了记忆库里后续Agent再检索时很容易被脏数据带偏编排逻辑没有写在代码里而是用“请一步一步来”“重复调用工具直到成功”这种话写在prompt里让模型自己决定什么时候继续、什么时候该停。这个结构最大的问题是没法单独调试。链路出问题时你分不清是模型理解错了还是工具实现错了还是记忆被污染了。这也能解释为什么现在社区里越来越多人在讨论“harness和agent区别”“agent框架与编排”“agent memory”——因为大家慢慢意识到Agent不能只靠一个模型加一堆工具就完事它需要清晰的边界来承载可维护性。把复杂逻辑全交给模型自由发挥短期很爽长期就是债。2.3 第三层没有观测就没有定位能力传统系统出了问题你可以看日志、看链路追踪、看指标。而很多Agent项目在设计时完全没有留观测点。没有观测的Agent系统一次执行就是一次黑盒你只看得到最终结果看不见中间过程。它到底调用过哪些工具、每一步用的什么输入、走了哪条分支、在哪一步触发了终止全都无从得知。更麻烦的是Agent有随机性。同一段输入第一次跑可能调用了工具A第二次跑可能选择了工具B第三次跑干脆没走工具直接输出。如果你没有把每次执行的关键字段记录下来出了问题想复现往往复现不出来。这也不是模型在“抽风”而是Agent本来就是一个概率性系统。概率性系统必须靠日志、指标、样本回放来管理不能靠人肉记忆。所以我会把“观测”放在所有清理动作之前。没有观测手段任何重构都是盲人摸象有了观测手段你才能知道“屎山”具体堵在哪一层。3. 清一条Agent链路本质上是在清边界很多团队聊Agent治理时第一反应是换模型、重写prompt、换框架。这个思路很危险。一个已经在线上跑的Agent系统真正的清理目标不是“重写得更好看”而是“清出边界让每个部分可以被单独解释、单独测试、单独替换”。3.1 别急着重构先盘点真实调用链如果让我去处理一个难维护的Agent项目第一步不是改代码而是拿着代码、日志、配置把系统里所有Agent链路画一遍。画的时候重点写清楚从用户输入到最终输出会经过哪些模块哪些工具可能在什么时候被调用记忆库在什么时候被读取、在什么时候被写入哪些分支是代码写死的哪些是让模型自由发挥的。画完之后通常会浮现出几个特别扎眼的事实很多工具注册了但从来没有被调用过有几条prompt规则之间根本是互相矛盾的某个链路里有一段已经被废弃的重试逻辑但没有人删掉还在继续消耗token多个Agent共享同一个工具但每个Agent对这个工具返回格式的解析方式都不一样。这些信息不盘点是不会浮出水面的。清理“屎山”的第一步永远是“搞清楚现状”而不是“我觉得这里应该那样改”。3.2 工具层、记忆层、编排层要分开在盘点完现状之后真正值得动刀的地方不是某个prompt写得好不好而是模块边界。一个可维护的Agent系统在结构上应该尽量把这几件事拆开工具层只负责执行单个动作返回值必须是结构化、可预期的不感知业务流程记忆层只负责数据的存取和检索不决定任务走向定期清理过期和低质量记忆编排层决定调用顺序、终止条件、异常处理这部分是工程代码最好放在代码和配置里不要丢给模型Prompt层定义Agent的角色、表达方式和约束复杂业务逻辑尽可能不塞进prompt。这样改完之后最大的变化是当工具返回异常时你只需要看工具层当上下文被污染时你只需要检查记忆写入逻辑当Agent绕过了某个必要步骤你去查编排层和prompt边界。问题可定位比能力优化要优先得多。这也是为什么我认为如果只是为了让Agent“更会聊天”“更像真人”可能不需要把工程结构搞这么复杂但一旦要把Agent放到真实业务里用——对接客户、处理订单、查询内部系统——边界和分层就是必修课。3.3 Skill、Tool、MCP不是越丰富越好最近关于Agent能力的讨论很多很多人开始研究Skill、Tool、MCP这些概念。我的理解是这样的Tool是Agent可以直接调用并获取结构化结果的最小执行单元Skill可以理解为带有流程的复用能力把几段常见操作组合成特定技能MCP更多是面向工具接入的标准化方式让Agent按统一协议发现并调用外部能力。注意不要因为市场上的概念和框架很多就把所有东西都往Agent里堆。一个上下文窗口有限、记忆检索能力一般的Agent如果挂了50个工具、注册了20个Skill实际表现大概率不会更好只会更糟每次决策时搜索空间变大误选工具的概率上升运行成本成倍增加。清理这类问题的常规思路是先做减法。把Agent只暴露给当前任务真正需要的那几个工具把偶尔才用的能力挪到“按需加载”。这不是技术倒退而是给Agent降噪。真正让Agent变强的不是工具数量而是在有限上下文里把最合适的工具和信息送到模型面前。4. 为什么“清理Agent屎山”正在变成一门生意有人会对“生意”两个字感到好奇清理技术债不是每个团队该自己做的事吗为什么会有人愿意花钱请别人来做站在这个时间点我认为有几个因素正好凑到了一起。4.1 Agent项目集体进入维护期这是时间窗口从2023年起不少公司已经做过一到两轮Agent尝试。早期那些跑通demo、做出效果、完成内部汇报的Agent现在大多已经变成了“半成品系统”功能上了、效果还行、但没人愿意长期接手。当初负责调研和Demo的人可能已经换了项目新来的团队一看代码复杂度超出预期文档基本没有测试基本缺失会陷入“看得懂局部、看不懂整体”的处境。与此同时企业主很少接受“推倒重来”的方案。因为Agent确实在跑业务也确实在用只是它变得越来越难加新东西。老板的诉求通常很朴素别崩、能继续加功能、出了问题能快速定位。这个诉求天然指向的不是“重写”而是“清理”“整理”“加固”。4.2 企业需要的是“不破坏现状的可维护性”如果去问一家正在被Agent“屎山”困扰的公司它需要的到底是什么答案往往不是“一个更先进的Agent架构”而是“现状还能继续用但希望它不要变成定时炸弹”。这意味着清理业务的交付物和“开发一个新Agent”完全不是一回事。开发新Agent的时候你可以自由选择框架、模型、prompt结构怎么顺手怎么来。清理“屎山”的时候大多数情况下不允许大拆大建。你要在一个已经跑起来的系统上做切片手术补日志、抽公共逻辑、统一返回格式、去掉互相矛盾的prompt规则、接入测试样例。每一步都必须小心不能今天改完明天流程就废了。这种“不破坏现状的可维护性”就是典型的存量服务。而存量服务通常是被普通开发者嫌弃的改别人的乱代码、处理历史包袱、不能大刀阔斧。但换个角度想麻烦和稀缺正是服务定价的空间。4.3 这门生意的交付物到底是什么结合我看到的情况我给这类业务梳理出几种典型交付物诊断报告不是泛泛而谈的“你代码写得很乱”而是把真实调用链画出来、标出高风险节点、指出哪些链条已经没有人维护、哪些prompt规则互相冲突最小改造先处理最影响线上稳定性的几个问题不做全面重写维护规范形成一整套prompt变更流程、工具接入标准、日志字段要求和回归用例集让客户自己的工程师以后按标准执行基础培训教客户团队如何看Agent日志、如何排查一次失败链路、如何在不破坏其他链路的情况下新增工具。收费方式也很多样有一次性的诊断费有按几个月到稳定期的固定项目费也有每周来看一次系统状态的订阅服务。但核心都一样公司买到的不只是一段代码而是一个“以后不用再提心吊胆改Agent”的能力。5. 一套可复用的Agent清理路径前面几章更像是在解释“是什么”和“为什么”这一章写怎么做。如果你手头也有一个已经不太能动的Agent系统或者你未来可能接到类似的清理需求可以按下面这条路径走。5.1 第一步建立基线先有日志再谈清账清理的前提是掌握信息。所以无论系统现在多乱都先补最基础的一层结构化日志。日志字段需要能够回答这些基础问题这次请求是谁发起的、用了哪个Agent、调了哪个模型、用了哪个prompt模板、上下文有多长、调用了哪些工具、每个工具的输入输出是什么、最终结果是什么、有没有失败、失败在哪一步。一个常见的记录结构可以长这样{ request_id: req_20250101_abcd, agent_id: order_intake, session_id: sess_123, model: gpt-4o-mini, prompt_template: order_intake_v3, context: { system_prompt_chars: 1800, history_count: 12, retrieved_chunks: 4 }, tool_calls: [ { tool_name: query_order, input: {order_id: A1001}, output_summary: found 1 order, statuspaid, duration_ms: 230, ok: true } ], final_output: ..., error: null, total_tokens: 1820, cost_estimate_usd: 0.009, created_at: 2025-01-01T12:00:00Z }这只是一个示意实际字段取决于你的业务。核心原则是每条Agent执行链路都要留下足够的时间点信息。有了这份基线后面所有排查、优化、归因才有下手点。5.2 第二步从链路中切出最小可维护片段日志补好之后先不要碰整个系统只挑一个范围最小的核心链路来做改造。判断标准是这类执行在业务里出现频率最高或者它对线上稳定性影响最大。然后做切片列出该链路的每一个步骤把“可以确定的判断”从prompt里挪到代码里例如格式判断、条件分支、权限校验只把“真正依赖语义理解的判断”留给模型对模型返回的结构化字段先做一次校验不合格就自动要求重新输出而不是直接透传到下一步。这里有一个值得强调的边界不是所有判断都要挪出prompt。如果某个判断本质上依赖上下文和语义比如判断用户投诉文本是不是在表达不满那交给模型是合理的。如果是判断“订单状态是否为paid”这种明确条件那应该用代码而不是让模型去猜。这个边界划清楚你的Agent会一下子稳定很多。注意不是所有判断都要挪出prompt。能用代码判断的用代码需要语义理解的留给模型这个边界才是清理完之后系统能否保持稳定的关键。5.3 第三步补齐工程化能力很多Agent项目看起来乱不是因为Agent没写好而是缺少传统工程里那些“基本功”。清理时可以直接把这几个能力补上幂等一个用户请求被意外重试两次不应该产生两笔订单或两条通知重试区分哪些错误值得重试比如临时超时、限流哪些错误不值得重试比如参数错误、业务校验不通过上下文压缩当历史消息太长时先做摘要或裁剪而不是硬塞给模型输出校验对Agent返回结果做schema校验出错就走修复或人工兜底预算控制在代码层面限制单次任务的token上限、工具调用次数上限避免Agent无限空转。关于前面热词里反复出现的那些报错比如“agent execution terminated due to error”或者“did not respond in time”。从排查链路来看通常可以按下面这个顺序查先看日志这次失败发生在哪个阶段是模型调用失败、工具调用失败还是输出校验失败再看上下文是不是上下文超长、超过超时限制、token超限再看外部依赖工具服务是否可用、API是不是超时、模型服务有没有限流最后看参数温度、最大token、重试次数是否设置得符合场景。这四步走完大部分“Agent执行失败”都能定位到具体层而不是只能靠重试赌运气。5.4 第四步沉淀成检查和维护规范清理“屎山”的最后一步是把这次踩的坑变成下一次的检查清单。否则三个月后它又会重新长回来。建议沉淀的清单可以包括新增工具时要提供哪些字段返回格式是否符合统一规范修改prompt前要跑哪几条核心样例做回归上下文超长时的默认处理策略是什么记忆写入前是否需要先做摘要或过滤灰度发布Agent时需要对比哪些指标。如果团队规模不大这个清单可以是文档。如果团队规模大一点可以把部分检查点做成CI脚本或CLI。比如prompt模板变更后自动运行回归集工具接入时校验返回字段。规范的意义不是限制谁而是让“不确定”变成“可查”。6. 与其等“屎山”堆高不如一开始设护栏最后一部分想做一个提醒清理Agent“屎山”这门生意之所以能成立背后暴露的问题其实是很多人从第一天起就没有替Agent系统设置任何护栏。6.1 新Agent项目应该有的几道护栏如果你正在起一个新Agent项目与其将来花一笔钱请人来清理不如提前做几件投入不大、回报明确的事prompt模板化把prompt拆成角色、业务、约束、输出格式几个部分每个部分独立管理不把零散规则直接粘在代码里工具接入标准所有工具必须是结构化输入输出不搞“每个工具返回格式都不一样”的玩法日志从第一天就开哪怕日志字段还不
返回列表