过去两年里,我一直在生产环境中构建并拆解 AI agent。一路走来,我一再看到同样的模式反复毁掉系统。这并不是因为模型不够好,而是因为系统设计出了问题。
大多数 agent 的失败都是悄无声息的。它们在 demo 中表现良好,但一到生产环境就会不可预测地漂移。成本会突然飙升,却没有明确解释。
系统行为开始变得不稳定,而每一次发布都像在冒险。最终,团队会被困在 PoC 炼狱中,既无法真正上线,也无法调试,更谈不上信任自己的系统。
根本原因几乎从来都不是模型本身,而是那些看起来各自都不大的系统设计错误。它们会层层叠加,最终演变成生产事故。
为了解决这个问题,我和 Louis-François Bouchard 一起整理出了一套诊断框架,专门对应 6 类会让 agentic 系统在生产环境中崩溃的具体错误。每一种错误都有明确的问题表现、成因,以及经过验证的修正方法。一旦你知道该看什么,大多数生产故障都可以追溯到这些模式中的某一种。
第一类,也是最常见的一类失败,就发生在输入层:工程师错误地处理了上下文窗口。
错误 #1:把上下文窗口当成事后补救
一旦系统出问题,人的本能反应就是继续往里塞更多上下文。工程师会添加更多规则、更多历史、更多工具、更多示例。背后的假设是:如果模型看到了所有东西,它的表现就会更好。
但这样会把上下文窗口变成一个垃圾堆,而不是一块经过精心限定的工作记忆。随着上下文不断膨胀,模型开始忽略指令,并且不一致地应用约束。它会产生更多幻觉,在不同运行之间漂移。
延迟会飙升,成本也会不断叠加。这就是所谓的 lost in the middle 问题。很多团队对此的回应,是把一个巨大的 prompt 拆成几十个更小的 prompt。

但这又会引入它自己的问题,例如更多的 LLM 调用、更高的延迟,以及更难调试。
💡 请把上下文窗口视为一种稀缺资源。
每一次 LLM 调用都应该只有一个明确限定的任务。你必须在每次调用前积极地筛选上下文:做选择、压缩和裁剪。把持久化职责移到 memory 层。
上下文窗口里只保留下一次决策真正需要的内容,其他一切都应该放到 memory 中,由系统持续地写入和读取。

一个经验法则是:先从单个 prompt 开始。如果它能工作,就到此为止。如果它失败了,也不要立刻跳到 agents。
引入少量专门化步骤,再持续调优,直到找到平衡点。上下文工程的关键,在于有意识的选择。
一旦上下文窗口的问题被控制住,下一个陷阱就是:在问题真正需要之前,就把架构做得过于复杂。
错误 #2:一上来就使用复杂方案
你面对一个明确问题,于是立刻伸手去抓多 agent 架构或一整套重量级框架。你开始构建 RAG 管线、混合检索、多个数据库,或者引入像 MCP 这样的新协议。你这样做,并不是因为问题真的要求这些,而是因为这看起来像是构建严肃 AI 系统的正确方式。
每增加一层,都会附带隐藏税负。依赖变多,延迟变高,成本增加,调试难度也上升。复杂性会不断累积成运维痛苦。
团队最终会花上几个月搭基础设施,却什么也没有真正交付出来。
在我们的创业公司 ZTRON,我们曾构建过一个多索引 RAG 系统。我们有 OCR 管线、独立的 embedding 管线、混合检索,以及 agentic RAG 循环。
它确实能工作,但简单查询也要花 10 到 15 秒。成本不断上升,调试更像是一场噩梦。
当我们终于停下来问:我们真的需要这一切吗?答案是否定的。我们的数据其实完全能放进现代上下文窗口中。于是我们在大多数工作流里,把 agentic RAG 换成了 cache-augmented generation(CAG)。
这样一来,LLM 调用更少,延迟更低,错误更少,系统也更容易调试。

从能工作的最简单方案开始。先证明核心任务本身能跑通。只有在问题确实要求的时候,再加入 memory、tools、retrieval 或多个 agents。
真正能在生产中站住脚的 AI,是由那些先交付简单系统、再有意引入复杂度的工程师构建出来的。
所谓“赢得复杂度”,往往意味着你最终意识到:你甚至根本不需要 agent。这也就引出了第三个错误。
错误 #3:本来用工作流就够,却硬要上 agent
像数据摄取、摘要生成、报告生成这类可预测任务,需要的是可预测执行。这种场景适合工作流。像深度研究、或者在不确定条件下做动态决策这类开放性任务,才可能真正需要自主性。
agent 更适合处理这些开放性场景。但大多数团队会把那些可预测问题也当成需要 agent 的问题。你一旦在结构化任务上使用 agent,你就是在为自己并不需要的自主性买单。
你会得到不可预测的行为、波动的延迟、更高的 token 消耗,以及不稳定的输出。系统看起来在 80% 的时间都能工作,但偏偏会在最关键的时候失败。
工作流和 agent 并不是二选一。它们位于一个连续光谱上,这就是所谓的 autonomy slider。更高的自主性会带来灵活性,但代价是可预测性、成本控制和可调试性都会变差。
你必须有意识地设置这个滑杆。

采用 workflow-first 的方式。从 prompt chaining、routing、parallelization,或者 orchestrator-worker 模式开始。只有当系统必须自主规划、探索未知路径,或者需要动态从失败中恢复时,才引入 agent。
对于垂直领域 AI agents,更合适的方式是混合方案:已知模式走工作流,开放性请求交给 agent。
无论你用的是工作流还是 agent,最终都必须处理它们产出的数据,而这又暴露出工程师处理输出时的一个常见缺陷。
错误 #4:脆弱地解析 LLM 输出
你要求模型给出结构化输出,它也确实返回了“看起来像是结构化”的内容。于是你用正则、字符串切分,或者自定义逻辑去解析它。它在 staging 环境里跑得很好。
然后总有一天,少了一个逗号,或者 bullet 风格变了,生产环境就崩了。LLM 本身就是非确定性的。即便 prompt 完全一样,输出也会因为上下文变化、模型更新,或者工具输出差异而发生漂移。
脆弱的解析方式,就是一颗定时炸弹。很多团队的应对方式,是要求模型输出 JSON。这样确实比自由文本更好,但它依然不是契约。
你仍然会遇到缺失字段、错误类型,以及嵌套字段随时间漂移的问题。

不要再把 LLM 输出当成文本,而要把它当成数据。定义 schema,在生成阶段就强制遵守,在运行时做校验,一旦错误就立刻失败。使用 Pydantic,作为概率式生成与确定性代码之间的桥梁。
不过,只有在确实需要结构时才使用结构化输出。如果你只需要一段普通字符串,那就接受字符串,并把 schema 保持得浅而小。
当你已经控制好了上下文、简化了架构、选对了自主性级别,并对输出使用了 schema 约束之后,你才算真的准备好去构建 agent。然而,即便如此,很多团队仍会因为遗漏“规划”这件事而失败。
错误 #5:忘了 agent 需要规划
你给模型一组工具,让它挑一个来用,把工具输出再喂回去,然后重复这个过程。乍看之下,这似乎很像 agentic,但实际上它只不过是一个带随机性的工作流。系统只是在对最近一次工具输出做反应,而不是在朝着目标推进。
如果循环中没有嵌入规划能力,它就无法把任务拆解成真正有意义的步骤。它不能评估当前进展,也无法有意识地选择下一步动作。最终结果就是随机行为、无谓的工具调用、无限循环,以及浅层推理。
如果你只是照搬博客里的 ReAct 或 Plan-and-Execute,而没有根据自己的领域去适配,问题只会更严重。

你必须把规划嵌入循环之中。在调用工具之前,先要求一个推理步骤。让系统先回答:目标是什么?下一步最优动作是什么?我需要什么证据?
同时加入进度检查和终止条件,例如最大步数、token 预算,以及卡住时的升级策略。规划必须是面向具体用例的,因为通用版 ReAct 并不是产品。你需要让规划方式适配你的工具、数据、约束和失败模式。
即使一个 agent 已经具备良好规划,如果你不持续衡量它的表现,它仍然会随着时间退化。
错误 #6:从第一天起就没有 AI 评测
你在不断加功能,却不追踪 AI 的实际表现。你没有测试、没有评测指标,也没有定义成功标准。每增加一个新功能,都是一次赌博,而团队会在没有察觉的情况下把回归问题带到线上。
AI 系统不会一下子整体崩掉。它们是慢慢衰退的。一个 prompt 改动、一个新工具,或者一次模型升级,都会引发细微的行为漂移。
如果没有 evals,没有人能回答:这次改动到底让系统变好了还是变差了。团队最后只能依赖 vibe evals,也就是靠人工主观感觉做测试。这种方式无法扩展。很多团队以为自己做了评测,但实际上只是用了像 helpfulness 或 1-5 星这种泛化分数。
一个 3.7 分的 helpfulness,并不能告诉你到底应该修什么。

把 evals 当成你的北极星。从第一天起,就定义与真实系统行为和业务要求紧密绑定的、任务特定的二元指标。让 evals 驱动整个优化飞轮。
把 evals 集成到你的开发工作流中,在用户发现回归之前先把它们拦下来。
结论
识别出这 6 个错误,是逃离 PoC 炼狱的第一步。
这 6 类错误,并不是什么稀有边界案例。它们正是那些会在真实 agentic 系统中反复造成崩溃的典型模式。单独看时,每一种都不算大;但一到生产环境,它们会层层叠加,最后酿成灾难。
本文为学习目的的个人翻译,译文仅供参考。
原文链接:Agentic AI Engineering Guide: 6 Critical Mistakes。
版权归原作者或原刊登方所有。本文为非官方译本;如有不妥,请联系删除。