说实话我这些年见过太多 Agent 项目了演示的时候全场惊艳一上生产就被运维和客服轮番问候。这个Demo 惊艳、上线拉胯的现象不是段子而是企业级 Agent 落地最真实的写照。今天这篇文章我想把背后的根因和四条关键坎彻底讲透结合我自己做过的几个生产项目把踩过的坑、试过可行的工程解法一次说清楚。这篇文章适合这样的人大模型应用开发工程师、AI 平台负责人以及正在从做个 Demo 玩玩走向上线扛业务的团队。你不一定需要完整的生产级架构经验但只要你开始考虑 Agent 的稳定性、安全性、可观测性这篇文章就能帮你少走三个月弯路。1. 先聊清楚为什么 Demo 永远惊艳上线必然拉胯1.1 Demo 的假成功来自哪里我复盘过很多 Agent 项目基本都有一个共同点Demo 阶段的成功靠的是条件好、场景窄、有人兜底。先说条件好。做 Demo 的时候我们选的通常是模型最擅长的那几条路径输入输出都是精心设计的跑出来的效果自然是可控的惊艳。你很少会在 Demo 里让 Agent 去处理一个表达极其模糊、还带点方言和口语噪音的用户输入因为那不是演示的重点。再说场景窄。Demo 通常只打通一条核心链路用户提问、Agent 调一个工具、返回结果。没有复杂的多轮状态、没有并发压力、没有异常路径。你甚至不需要考虑用户前一句说的是 A 项目后一句突然问到 B 项目Agent 要怎么记住上下文边界和状态切换这种问题。最重要的是有人兜底。Demo 现场操作者是开发工程师自己。模型答偏了他可以补一句解释或者换个提问方式再来一次。但在生产环境里用户可不会帮你圆场。同一个问题换个问法Agent 可能就完全跑偏了上一次问过的东西这一轮突然失忆用户只会觉得这系统是个半成品。1.2 从演示逻辑切换到生产逻辑缺的是工程思维如果从工程角度拆开看Demo 和生产是两套完全不同的逻辑。Demo 的核心逻辑是证明它能做这件事所以我们追求的是上限把所有资源都押在让模型表现最好这一条路上。生产逻辑则完全不同它追求的不是上限而是下限——最差情况下的表现。系统 90% 的场景跑得很漂亮剩下 10% 的场景跑出了事故那这个系统在生产上就是不合格的。换句话说Demo 考验的是模型能力生产考验的是兜底能力。模型答错了怎么办工具超时了怎么办Agent 在循环里出不来怎么办敏感数据被工具读进上下文了怎么办这些问题在 Demo 阶段根本不会暴露但一上线全是事故。我会把这几个问题压缩成四道坎确定性坎、状态坎、工具坎、评估坎。下面逐个拆开讲并给出我验证过的工程解法。2. 第一道坎确定性——从自由发挥到流程可控2.1 概率模型撞上确定性系统矛盾怎么解LLM 本质上是概率系统同样的输入两次输出的结果可能不一样。而企业系统几乎都是确定性系统同样的单据同样的接口必须返回同样的结果。怎么调和这个矛盾我的答案很简单能不交给模型的地方绝对不交给模型必须交给模型的地方用结构化约束框住。我不反对用 LLM 做复杂推理但我极度反对把 LLM 当成万能胶水哪儿都粘一下。生产级 Agent 应该是一个确定性骨架 非确定性局部的混合体。拿一个客服工单分类场景举例。用户提交一个投诉工单标准的做法是第一步做意图分类第二步提取结构化信息订单号、用户 ID、问题类型第三步根据分类结果走固定的分支流程。这三步里第一步和第二步可以用 LLM 做但第三步的分支跳转应该用代码写死。如果你让 LLM 自己决定下一步调哪个工具、按什么顺序调短期看着灵活长期绝对出事——模型一旦选择了一条不在预期内的路径整个流程就失控了。2.2 用工作流编排把自由度降到最低工作流编排的意思是把一个复杂任务拆成多个环节每个环节定义清楚输入输出环节之间的流转由代码控制只有需要理解、生成或灵活处理的局部才调用模型。比如我做过一个企业知识库问答 Agent表面上是一个问一句答一句的对话系统但内部是严格按照工作流拆的意图识别判断用户是想查文档、查数据还是闲聊。文档检索走 RAG召回 Top 5 候选文档。信息提取从召回的文档片段里抽取与问题相关的信息。答案生成基于提取的信息用 LLM 生成回答并附上引用来源。其中第 2 步和第 4 步的工程含量特别高。第 2 步的检索排序我完全没让 LLM 参与直接用向量相似度 关键词权重混合排序。第 4 步生成回答时我要求模型必须在给定的文档片段内作答超出范围就回答未找到相关信息不许自己发挥。这套设计的核心价值在于任何一个环节失败我们都能精确知道失败发生在哪并且可以直接针对性重试或降级。如果第 2 步检索结果为空直接返回未找到根本不进第 4 步省一次模型调用也避免模型胡编。2.3 结构化输出与校验重试机制模型输出必须结构化这是生产落地的基本功。现在主流模型都支持 function calling 或者响应格式约束你要做的是把所有模型输出都收敛到一个 JSON Schema 里。我个人的习惯是定义严格的输出 Schema关键字段标注必填和类型然后做两层校验。第一层是格式校验模型返回的 JSON 必须通过 Schema 校验不合法就直接触发重试。第二层是业务校验比如返回的订单号必须存在于业务系统里不存在就视为失败。重试策略上我最多允许两次重试两次都失败就走兜底逻辑输出一个标准话术的暂时无法处理。这么设计的原因很简单与其后面让现场的人面对各种奇怪的模型输出不如在源头把输出约束死。宁可让 Agent 说我做不到也绝不允许它给一个格式正确但内容错误、甚至内容正确但格式混乱的答案。2.4 兜底与降级把最坏情况的方案提前写好生产系统里模型不可用、接口超时、上下文超长这些问题一定会遇到。我的做法是给 Agent 配一条降级链主链路大模型 工具调用满足 99% 场景精度需求。一级降级当模型超时或连续重试失败直接返回预设兜底话术引导用户转人工或留下联系方式而不是让用户等待。二级降级当某一类工具服务不可用时Agent 主动告知用户该功能暂时不可用其他问题我可以继续帮你处理保证对话不崩。这相当于给 Agent 装了一个紧急刹车。你不可能控制模型什么时候犯傻但你可以控制犯傻之后系统做什么。这条降级链Demo 阶段永远不需要生产阶段一天都离不开。提示我在生产环境里反复验证过温度参数在生产场景下通常设为 0 或者 0.1 就够了。不要为了更有创造性把温度调高因为生产场景要的是稳定不是创意。3. 第二道坎状态与记忆——从一问一答到有脑子的长会话3.1 无状态是 Demo 的习惯有状态才是生产的标配Demo 阶段最常见的写法是无状态用户一问Agent 一答结束。上下文全靠当前这一轮请求携带。但一旦上生产你就得面对现实用户会在同一个会话里连续问好几个问题甚至前后问题之间有依赖关系用户会中途切换话题用户关掉页面第二天回来期望 Agent 还记得昨天聊过什么。生产级 Agent 必须有状态管理。这个状态分两层理解第一层是会话状态。一次对话内部要维护最新的上下文快照包括历史消息、当前正在执行的步骤、已经获取到的工具结果。这样用户说刚才那个项目再细说一下Agent 才知道刚才指什么。第二层是长期记忆。跨会话的场景下用户的偏好、之前交代过的事项、历史订单信息需要被存储下来在新会话中自动被召回。这一层在 Demo 里几乎没人做但它是企业用户体验的根本分水岭。3.2 把状态从内存搬到外部化存储无状态开发最简单所有状态都在内存里进程一重启全没了。生产上必须把状态外部化。我推荐的组合是会话状态放 Redis、持久化记忆放 PostgreSQL 或者专门的向量库。会话状态存取频率高、数据量小Redis 的 TTL 机制又能天然处理会话过期问题。我一般给会话设 30 分钟到 24 小时的过期时间根据业务场景来定。长期记忆则走数据库按用户 ID 聚合存储服务于跨天甚至跨月的记忆召回。这里有个特别容易被忽视的点状态快照的粒度。我不建议把整个对话历史原封不动地塞进上下文。生产环境里上下文窗口是宝贵资源最好做分层管理最近的几轮完整消息完整保留更早的消息做摘要压缩长期偏好单独存成结构化字段。这样既保住对话连续性又控制 token 成本。我就在一个项目里遇到过这种情况用户和 Agent 聊了一个多小时历史消息堆积了十几万 token结果后续每问一个问题响应都慢得离谱。后来我把历史策略改成近 6 轮保留原文 更早内容自动摘要 关键信息结构化抽取到记忆区响应时间直接降了一个量级而且用户明显没有感知到失忆。3.3 检查点机制让 Agent 具备后悔药状态管理还有一个进阶功能——检查点。这是我从工作流引擎里借鉴过来的思路。Agent 每执行完一个步骤就把当前状态持久化一次。一旦后续步骤失败或模型连续几次都无法完成任务就可以回滚到最近一个正常状态重新规划下一步。举个实际场景Agent 在执行查询订单 - 核对账单 - 发起退款三步流程时第一步成功了第三步失败了。如果没有检查点用户必须重新发起整个请求Agent 也要重新查一遍订单。有了检查点系统可以直接从核对账单那一步的状态恢复跳过错综复杂的开头直接重试最后一步。检查点的实现不复杂核心就是把状态序列化后存到 Redis 或数据库带上一个执行步骤 ID。真正难的是在回滚到什么程度上做选择我建议回滚到最后一个成功的工具调用之后而不是回滚到对话最开始这样能最大程度保留已经取得的进展。3.4 记忆的安全边界该忘的一定要忘记忆是双刃剑。记住了用户偏好体验会很好记住了不该记的内容合规风险直接爆炸。我在设计记忆系统时至少有这么几条红线敏感信息不进长期记忆。身份证号、银行卡号、密码等一律只允许在当次会话内临时出现禁止写入长期存储。用户可控制记忆。提供清除我的记忆入口这是基本功能不做就等于埋雷。记忆需要分级。业务数据和用户行为偏好分开存储业务数据按业务单据为准偏好信息按用户 ID 存储两者不混在一起。说到底记忆是为了让对话更有连续性而不是为了让系统变成一个偷窥狂。边界越清晰后续的合规审查和安全审计越省事。4. 第三道坎工具调用——从假数据摆拍到真系统联调4.1 Demo 用 mock生产接真系统差异在哪Demo 阶段最常见的一个偷懒操作是工具函数内部直接返回写死的 mock 数据。看起来 Agent 调工具调得很流畅其实工具只是一个摆设。生产环境一接真实 API立刻暴露问题权限怎么办参数校验谁来做接口挂了怎么处理重复调用会不会造成重复扣款工具调用的本质是让 LLM 具备操作系统能力但这也意味着一个问题模型一旦能调工具就能以非常奇怪的方式调用工具。它可能传错参数、可能漏掉必填参数、可能在一次任务里重复调用同一个写操作接口。这些都不是模型能力问题而是工程防护问题。4.2 工具接入的三层防护网我总结了一个工具接入的标准三层防护模型每个接入生产环境的工具都必须过这三层。第一层工具路由与参数校验。所有模型要发起的工具调用先经过一个路由层。路由层维护一个工具白名单不在名单里的调用直接拒绝。参数校验在这里做掉必填字段、类型、取值范围、枚举值全部校验一遍不合法就要求模型重新生成调用。这一步能挡掉 90% 的异常调用。第二层权限控制。工具级权限是必须的。同一个工具不同角色能调用的数据范围不同。比如查询订单这个工具普通用户只能查自己的订单客服人员可以查所有订单管理员还能查内部备注。权限判断不能在工具内部做要在调用链路的上一层统一做这样审计日志才完整。第三层运维防护。包括超时限制、重试机制、熔断器。我给每个工具调用设置了超时即断策略模型调用工具等待时间超过 10 秒立刻返回超时异常由编排层决定是重试还是降级。熔断器的逻辑是如果某个工具在 1 分钟内连续失败超过 5 次直接熔断 30 秒期间所有请求都走降级路径避免连锁雪崩。4.3 响应截断与上下文护栏工具返回的数据通常很大——一个订单列表可能几千条记录一次数据库查询可能返回几万行。把这些数据全塞进模型上下文既浪费 token又会让模型迷失在无关信息里。我的处理方式是在工具调用结果返回给模型前先做一轮精简。只要结构化提取其中的关键字段把与当前任务最相关的部分保留下来。如果结果太长优先做聚合摘要只展示 Top N 条并明确告诉模型完整的明细在附件里需要时可以再调用接口获取。这一层截断的逻辑必须由工程师主动设计绝不能靠模型自己取舍。另外工具的返回结果里还可能混着敏感信息。比如查询用户订单时后端返回了用户的手机号、地址、支付账号等字段这些字段对判断订单是否异常没有任何帮助却会被模型读取。所以我在工具层会做一次字段脱敏把不需要的敏感字段直接摘掉再进模型上下文。这个动作成本不高但对安全合规的价值非常大。4.4 幂等设计防止 Agent 把一件事做两遍Agent 调用工具失败后的重试机制会引入一个经典问题第一次调用其实成功了只是响应超时所以系统判定失败并重试结果同一个写操作被执行了两次。在退款、下单、修改权限这类场景下这就是事故。解法是幂等设计。所有写操作工具必须要求调用方传入一个业务幂等键。服务端根据这个幂等键判断是否已经执行过相同的操作是就直接返回第一次的结果否才真正执行。这个思路不复杂但很多团队做 Agent 时完全没考虑直到出现重复扣款才知道疼。我在一个财务 Agent 项目里因为这个幂等设计救过一次场Agent 在退款时超时重试了一次第一次其实已经退款成功第二次调用因为幂等键相同被服务端拦截返回了该退款单已处理。假如没有这道防护用户会收到两笔退款而财务系统完全不知道第二笔钱是从哪儿出去的。注意凡是涉及真金白银、权限变更、数据删除的工具调用一律要过幂等校验 视风险等级人工审批。不要觉得审批流程烦这个烦能拦住 99% 的严重事故。5. 第四道坎评估与可观测性——从人眼看效果到系统看指标5.1 上线之前先回答怎么算好很多人做 Agent 的时候对效果的判断全凭自己问几个问题聊几句。这种主观感受在 Demo 阶段够用在生产阶段绝对不够。因为模型更新一个版本、提示词改一句话、工具返回结构调整一下效果可能就变了而你完全不知道是变好了还是变坏了。我的做法是在写功能代码之前先写评估集。评估集就是一组样例 每个样例的预期行为判定。评估集不用大先从 20~30 个覆盖核心场景的用例开始后面逐步扩充到几百个。每个用例包含输入、辅助上下文、预期结果以及多个维度的评价标准。维度怎么定我的经验是两个层面。一是结果正确性比如用户查询订单时返回的订单号是不是用户自己的订单号。二是流程合规性比如 Agent 在处理退款请求前是否先获取了用户的身份认证信息。这两个维度缺一不可前者管结果后者管过程。每次改动之后跑一遍评估集对比通过率。通过率下降就是改动有问题通过率稳定或上升才允许合入上线。这其实就是把Agent 开发转成了可回归验证的工程过程不是再靠肉眼。5.2 全链路追踪给 Agent 装上行车记录仪生产环境的 Agent 调用链路很长用户请求 - 意图识别 - 检索 - 模型生成 - 工具调用 - 工具结果回流 - 二次生成。任何一个环节出问题用户看到的是这系统傻了但你不知道傻在哪一步。所以必须做全链路追踪。每个请求分配一个唯一的 trace ID从入口一路透传到所有内部调用和外部 API 调用。关键节点记录耗时、输入输出摘要、token 消耗、调用次数。一旦用户报障拿到 trace ID 就能像放录像一样回放整个决策过程快速定位是模型理解错了、检索没命中、还是工具返回异常。可观测性做得好的团队上线第一周就能通过 trace 发现大量预想不到的问题比如用户在凌晨集中提问但检索服务在凌晨有定时任务导致响应变慢这种问题不做 tracing 根本无从下手。5.3 运行指标与护栏除了逐条追踪我还建议建立一套在线运行指标。至少包含这几项请求成功率Agent 完成响应的比例。平均响应延迟关注 P50、P90、P95。平均工具调用次数超过预期值说明 Agent 可能在绕圈子。Token 消耗趋势可以当成成本监控指标。转人工率用户主动转人工的比例是体验恶化的信号。这些指标配上阈值告警就能把系统变差从用户抱怨提前到指标异常发现。我一般把工具调用次数的阈值设为正常路径调用次数的两倍一旦超过立刻告警并抽查对应 trace大概率能发现死循环或规划异常。5.4 内容脱敏与安全护栏Agent 的输出会直接触达用户输出内容的安全审查是硬性需求。我的做法是在模型输出之后加一道检测层私密信息检查、PII 识别、敏感词过滤。检测不过就拦截输出替换成标准安全话术。这道检测层放在输出侧看起来多了一次调用成本但对于企业场景来说它的价值完全覆盖成本。尤其是涉及医疗、金融、政务这些领域输出侧的一句話合规性问题都可能是严重后果。安全护栏和业务效果可以分开做两个团队各管一段但责任边界必须清晰。经验上线初期宁可在护栏上多花点成本也不要为了省那一点 token 钱把风险敞口留给用户。所有安全事故的成本都会十倍百倍地高于你省的算力成本。6. 一个可落地的生产级 Agent 架构参考6.1 分层架构总览聊了这么多理论我把它整理成一个我在多个项目里反复验证过的参考架构。这个架构一共分五层每一层解决一类问题层与层之间用接口隔离。接入层负责接收用户请求做身份认证、会话管理、频率限制。编排层是核心管理工作流、状态机、工具调用编排。记忆层做会话状态和长期记忆的存储与检索。工具层封装所有外部系统调用统一做权限、校验、幂等、超时处理。最后是观测层跑评估集、追踪链路、记录指标、执行护栏。这套架构不绑定任何特定框架。你可以用 LangGraph、CrewAI、agno 或者自己写一套编排引擎都可以。关键是每一层的职责要清晰不要把所有逻辑都堆在一个万能 Agent 类里。6.2 关键设计取舍这个架构里我最想强调的一个取舍是编排层必须支持确定性工作流和自由式 Agent两种模式混用。有些任务是完全确定性的比如查订单 - 判断状态 - 展示结果直接用代码写死流程中间没有模型决策点这样的链路快、稳、便宜。有些任务是不确定性的比如根据用户的一句话杂糅需求决定查订单还是查物流再给出综合结论这种才需要模型来做规划和决策。生产级系统的常态是大部分请求走确定性工作流只有少部分复杂请求才触发自由式 Agent 模式。不要一上来就全上自由式编排那是性能、成本和安全的三重灾难。6.3 配置示例伪代码我把上面这套设计简化成一段伪代码方便理解整体关系的组织方式。# 生产级 Agent 配置示例伪代码 agent create_agent( modelgpt-4o, temperature0.1, task_schemaTaskSchema( # 结构化输出 Schema intent(query_order | query_logistics | fallback), order_idstr, confidencefloat ), workflow[ Step(nameintent_parse, executorllm), Step(nameorder_query, executortool), Step(nameresponse_generate, executorllm) ], toolsregister_tools( QueryOrderTool( required_permissionorder:read, # 权限 idempotentFalse, # 只读操作不需要幂等 timeout10, response_truncate500 ), RefundTool( required_permissionorder:refund, idempotentTrue, # 写操作必须幂等 need_human_approvalTrue, # 高风险操作走人审 timeout15 ) ), memorySessionMemory( storeRedisStore(ttl3600), history_strategylast_6_rounds_full earlier_summarized ), checkpointCheckpoint( save_each_stepTrue, rollback_tolast_successful_tool_call ), guardrailGuardrail( max_iterations8, max_tool_calls_per_task12, output_filterPIIFilter() ) )这个配置虽然不是可以直接跑的实际代码但它代表了我在生产项目里最终沉淀下来的关键参数。哪一项参数出问题我都踩过坑建议你根据自己业务的节奏逐步调整不要照搬。7. 常见问题与排查技巧实录7.1 问题速查表我把生产环境里高频出现的几个问题整理成了表格完全可以当成排查手册用问题现象可能原因排查思路推荐解法同样的输入两次返回不一致温度参数过高提示词有歧义上下文里有干扰信息查 trace 对比两次模型输入输出温度降为 0输出改 JSON Schema精简上下文Agent 反复调用同一个工具不往下走工具返回结果没有让模型得到任务已完成的判定看 trace 里的循环段设置 max_iterations在提示词里明确获取到结果后停止调用对话到第 5 轮开始答非所问上下文超长早期信息被截断或稀释对比前几轮和后面的模型输入 token 分布启用历史摘要关键信息抽取到结构化记忆工具接口偶发超时用户等待很久第三方依赖不稳定缺少超时和降级看工具层耗时和错误码加超时限制加熔断超时后直接走兜底话术用户反馈 Agent 说到了他人的隐私信息工具返回字段未脱敏模型读到了多余字段查工具返回日志和模型输入记录工具层强制脱敏仅返回任务必需字段修改一条提示词后其他场景效果集体下降缺少评估集回归改动影响被忽略跑全量评估集对比通过率建立核心场景评估集改动必须过回归Agent 偶尔生成 token 量巨大成本飙升上下文塞入过多历史或工具结果查 trace 的 token 消耗明细做上下文裁剪工具结果截断历史摘要压缩7.2 我最想强调的两次踩坑复盘第一个坑是重试导致重复执行的坑。当时上线一个数据订正 Agent工具调用超时后无条件重试结果同一个更新语句被执行了两次数据被改出了异常值。后来我花了大半天做数据回滚才把线上数据修复。从那以后所有写操作工具一律幂等设计超时场景只警示不自动重试。第二个坑是评估集建得太晚的坑。项目已经开发了两个月才想起要建评估集结果发现很多历史改动都没有留下当时的输入输出对照完全无法判断哪些改动是有效优化、哪些是负优化。后来推倒重来花了两周时间补评估集才把开发流程拉回正轨。如果你正处在项目早期我建议你把评估集建设当成和功能开发同样重要的事项来安排。7.3 给新团队的实用建议如果你的团队刚从 Demo 阶段走出来不要试图一步到位把上面所有机制全上了。工程改造最怕大跃进。我的建议是分三个迭代周期来做。第一个周期先搞定工作流编排和结构化输出稳住确定性和效果下限。第二个周期补状态管理和工具调用的权限、幂等把生产安全红线划清楚。第三个周期再上评估集、全链路追踪和监控告警形成持续迭代闭环。每个周期大概两到四周三个周期下来差不多一个真正能上生产、能扛业务波动的 Agent 系统就成型了。自己在多个项目里验证之后我最深的体会是Agent 生产落地难的不是模型、不是提示词而是工程上的紧箍咒。越规范的约束Agent 越可靠。这篇内容里提到的很多解法其实都是常规工程手段在 LLM 场景里的重新组合没有什么神秘的高深技术。你只需要踏踏实实把每一步都做到位Demo 到生产之间的距离远没有想象中那么大。