带过三个从 Demo 落到线上的 Agent 项目之后我对“生产级 AI Agent 工作流”这几个字有了完全不同的理解。这个词看上去像是一个技术方案实际上是一整套关于稳定性、成本、失控风险的系统工程。今天不聊概念直接讲我是怎么把一条“能用就行”的 Agent 链路改造成能在线上稳定跑、能排障、能算钱的完整工作流。如果你也正在从原型走向产品这篇内容会帮你少踩很多我踩过的坑。先说一个大多数团队都会踩的坑很多人把 Agent 项目做出来之后第一反应是“能跑就行”然后直接丢到线上结果第一天就翻车。有的问题是模型突然返回一段和业务无关的闲聊有的是工具调用失败导致整个会话卡死更常见的是月底一看账单成本高到让人怀疑人生。这不是模型不行而是你还没把它放进一个生产级的工作流里。所谓工作流不是一串 Prompt而是一整套能够约束模型、控制风险、度量结果的工程骨架。1. 为什么生产级 Agent 这么难做1.1 一个容易被低估的问题生成的偶然性开发和跑通一个 Agent 可能只需要几天但线上稳定运行几个月才是真正的挑战。LLM 每次返回的内容不完全一样同一个 Prompt 今天可能输出一段标准的 JSON明天就可能在 JSON 前后多了一句“好的我来帮你查询”。这种随机性在 Demo 里是特色在生产里就是事故。生产系统需要的是可复现、可回滚、可回归而生成式模型天然不具备确定性。所以第一步不是调整 Prompt而是把所有不确定性来源列出来用工程手段一个个围住。举个例子做一个简单的“订单查询助手”你在测试环境反复调用模型大概率都能返回正确的订单号。可一旦放到线上用户的问法千奇百怪模型可能在同一个槽位上给出多个值甚至把订单号与日期混淆。如果不做校验和强制结构后面所有流程都会拿到脏数据。我们最初把这类问题当“模型不够聪明”去处理后来发现真正缺的是一个带有状态和校验的框架。我自己的体会是别指望模型“自觉”遵守规则。所有生产上必需的规则必须下沉到代码里校验比如输出格式校验、字段枚举校验、内容长度校验。模型负责生成候选工程负责判断能不能用。这个分工一旦确认后面所有设计都顺了。你可以在代码里加一层“结果校验器”专门负责把模型输出里的非法内容拦在业务逻辑之外。1.2 生产环境的约束条件时延、成本、资源线下体验一个 Agent慢几秒无所谓。线上每一个请求都在消耗 Token模型推理要时间外部 API 也要时间工具调用还可能卡住。成本按量计费延迟影响用户体验。一个生产级工作流必须给每个环节设置时间预算和 Token 预算。我们常用一句话约束团队不要设计一个无法回答“单次请求花了多少钱”的系统。算一笔账。假设一次客服工单处理需要 3 轮模型交互每轮输入输出加起来约 4000 个 Token按主流定价估算单次成本大概在几分钱到几毛钱之间。看着不多但一天一万次工单就是几百到几千元的成本。如果状态机设计得不好让模型在无关分支上多转了两圈成本会翻倍。所以生产级设计必须对每一步都“精打细算”该收敛时就收敛。时延同理。模型推理本身就要一两秒工具调用又要一两秒如果还允许模型自由循环调用用户等待时间会迅速超过可接受阈值。我们在生产环境里强制设定了 Agent 的“最大步数”和每个工具的超时时间超过就终止并转人工。这个限制看起来简单却能阻止大多数线上事故。你要在系统设计时就想清楚什么情况下允许 Agent 继续思考什么情况下必须停下来。1.3 生产级 Agent 的四个硬指标稳定、可控、可观测、可算账我把生产级 Agent 的验收标准收敛成四个硬指标缺一个都算不上“生产级”。指标具体含义缺失时的后果稳定可用性达标单个工具报错不会导致整体挂掉一次 API 抖动就让整个业务不可用可控行为可约束输出格式可控工具权限可控模型自由发挥出现越权操作可观测调用链可追踪每个环节有日志和指标出了问题只能靠猜无法定位可算账成本可核算每次请求能对应到业务指标月底账单爆炸不知道钱花在哪如果这四个指标没有在设计阶段就规划好等项目上了线再补会非常痛苦。稳定依赖超时、重试、降级可控依赖状态机和权限设计可观测依赖统一的 trace_id 和日志规范可算账依赖请求级的 Token 计数器。这些都不是模型能力而是工程底子。很多人觉得 Agent 项目的核心是模型但真正决定它能不能上线的恰恰是这些看起来不那么性感的工程能力。2. 工作流整体设计从自由对话到可编排2.1 状态机把“智能”收敛到确定的流程里最初我们的 Agent 是聊天式的用户随便说Agent 随便接除了爽快一无是处。后来线上开始有业务方抱怨“它有时候会自己跑到某个流程里去”才意识到自由对话不等于自由流程。把一次任务拆成“受理→信息收集→识别→查询→生成方案→确认→完成”每个阶段定义入口条件和出口条件就形成了一个状态机。状态机不是限制 Agent 智能而是把智能放在“每个节点做什么”上。# 状态机编排伪代码示例 STATES { collect: {next: classify, tools: [ask_user]}, classify: {next: search, tools: [intent_classify]}, search: {next: solution, tools: [query_order, query_faq]}, solution: {next: approval, tools: [generate_solution]}, approval: {next: done, tools: [submit_approval]}, } def run_agent(workflow, user_input): state collect while state ! done: allowed workflow[state][tools] result llm_call(state, user_input, allowed_toolsallowed) state validate_and_next(result) # 必须校验后流转 return result状态机天然解决了三个问题流程可追踪、异常可定位、权限可控制。出错时我们知道是在哪一步出的错而不需要把整个对话历史翻出来。自由对话模式很难做到这一点因为每一步都是模型临时决定的没有固定边界。把任务拆成确定的状态之后你还能在状态之间插入人工审批、条件判断、超时处理这些都是生产系统必须的能力。2.2 Agent 的工具设计既要给能力也要上锁工具调用是 Agent 能力核心。生产环境里工具即权限不能随意放开。我们维护一张工具清单每个工具包含名称、描述、参数 Schema、超时时间、权限级别、错误码。描述特别重要因为模型根据描述选择工具。如果描述含糊模型就会把“查询订单”和“查询物流”搞混。描述要写“什么场景下用、需要哪些参数、返回什么结果”不要写“查询数据的函数”这种模糊话。{ name: query_order, description: 根据订单号查询订单基础信息仅用于售后和物流场景, parameters: { order_id: { type: string, pattern: ^[A-Z0-9]{12}$, description: 12位订单号 } } }除了 Schema还要注意三点。第一工具内部必须做参数白名单校验模型给了非法值直接拒绝不要向下游传。第二工具返回结果一定要标准化成功返回数据失败返回错误码不要用自然语言描述“我失败了”。否则后续逻辑没法判断到底发生了什么。第三工具执行要记录审计日志尤其是涉及退款、发货、修改权限的工具后续扯皮时这是唯一证据。2.3 上下文与记忆的分层设计不能把所有历史都塞给模型。生产成本和上下文长度成正比而且超过一定长度模型注意力会下降。我们采用三层记忆策略。会话内记忆只保留最近 N 轮完整对话和当前任务的关键字段业务记忆把用户偏好、历史处置摘要放外部数据库按需检索注入静态知识把 FAQ、商品参数等放向量数据库用 RAG 检索相关片段。三层之间有明确的读取接口不是一锅炖。还要给每个请求设置上下文窗口上限。比如“单次请求的 Prompt 不超过 6000 Token超出时把最旧的对话压缩成摘要”。压缩策略要单独评估不能随意丢否则用户问“我刚才说了什么”时 Agent 会失忆。我的经验是宁可每次多花一点时间做摘要也不要把所有原始历史全部塞进去。摘要做在离线任务里线上只取摘要和最近对话效果和成本都更可控。2.4 可观测性日志、追踪、评估Agent 工作流比普通接口复杂。一次处理可能涉及模型调用、工具调用、状态跳转、人工介入任何一个环节出问题都会表现为用户侧的“答非所问”或“卡住”。我们上线了“三段式可观测”实时日志、链路追踪、离线评估。实时日志记录每一次 LLM 调用的 Prompt 和 Completion 摘要、Token 数、延迟、工具调用参数和返回码。链路追踪用一个 trace_id 贯穿请求全链路同时关联业务订单号。离线评估定期用脚本回放历史工单统计任务完成率、格式合格率、工具误用率。如果发现线上异常第一件事不是改 Prompt而是顺着 trace_id 把当时的输入、模型输出、工具返回全部捞出来看到底是模型选错工具还是工具返回了脏数据还是状态机跳错了分支。没有这个基础设施排障就像蒙着眼睛修车。你可以先花两天时间把日志结构定下来后面所有迭代都会受益。这个投入绝对值得。3. 核心模块工程化要点3.1 模型与服务商的选型策略不要一个模型解决所有问题。我们通常按任务类型切分意图识别、槽位提取用轻量快速模型要求低延迟、低成本工具选择、复杂推理用大模型要求较强的指令遵循能力摘要生成、推荐回复用中等模型平衡效果与成本。这么做的原因很简单线上请求的难度分布很不均匀一部分请求根本不需要大模型介入。做选型时建立一个评估集至少覆盖 500 条真实业务数据统计成功率、格式合格率、平均 Token 消耗和 P95 延迟。模型不是越强越好关键是“这个任务是否值得这个价”。比如客服场景70% 的请求是查订单和退换货规则用轻量模型就够了只有难缠的 Case 才升级到大模型。多个服务商之间要预留切换开关和适配层避免单点依赖。这个适配层可以是一层统一的 LLM 调用接口上层代码不感知具体服务商。3.2 结构化输出与工具调用的工程实现生产级要求模型输出可直接被程序消费。最简单但最不稳定的做法是“请你返回 JSON”写在 Prompt 里模型偶尔会多解释几句偶尔会把 JSON 藏在代码块里。我们更推荐使用模型平台提供的结构化输出或工具调用能力让模型返回一个符合 Schema 的结果。如果平台不支持也要在外面包一层“Prompt 解析 校验 修复”的代码。def call_llm_with_tool(user_input, tools): resp llm.chat( messages[{role: user, content: user_input}], toolstools, tool_choiceauto ) candidate extract_tool_call(resp) # 从响应中解析工具调用 if not valid_tool_call(candidate): # 二次修正把错误信息返回给模型让它重新生成 resp2 llm.chat( messages[...] [{role: tool, content: invalid: ...}], toolstools ) candidate extract_tool_call(resp2) return candidate这段代码说明一个常用技巧遇到解析失败不要直接报错把错误原因拼回去让模型重新生成一次成功率能显著提高。同时要对输出做业务校验比如日期格式、订单号格式、金额范围。保存原始模型返回和清洗后的数据方便事后查证。我们内部叫“脏数据保留原则”所有被修正过的输出都单独标记定期分析这些修正原因反过来优化 Prompt 和 Schema。3.3 重试、超时、降级和熔断任何线上系统都要面对网络和服务不稳定。模型 API 偶尔会超时工具 API 偶尔会返回 500用户输入偶尔会触发极端 Case。我们需要有三重防线。第一重是重试对模型调用和工具调用加入指数退避 随机抖动最多尝试 3 次避免连打加重问题。第二重是降级当主模型不可用时切到备用模型或直接走静态 FAQ当工具不可用时返回缓存数据或转人工。第三重是熔断连续失败超过阈值时自动停止调用一段时间保护下游系统。经验是超时时间一定要比重试总时间短否则用户会等很久。我们一般设置首轮超时 5 秒重试三轮总共不超过 20 秒超过就进人工队列。这个数字需要根据你的业务场景调整但原则一致永远给用户一个明确的结束状态而不是无限转圈。生产系统最怕的其实不是失败而是“没有结论的失败”。3.4 成本控制与限流策略成本失控是生产级 Agent 最常见的事故。一个 Agent 系统可能日请求量不大但一次请求烧掉的 Token 却很惊人。我从第一天起就要求每个请求必须带“成本 Tag”记录使用的模型、输入 Token 数、输出 Token 数、工具调用次数。每天汇总到成本看板按业务线分摊。没有这个机制你根本不知道是哪个功能在烧钱。还要做三层限流。用户级 QPS 限流防止某个用户刷接口功能级配额比如每个用户每天最多调用 Agent 20 次全局预算保护当每日成本超过预警值时自动降级或熔断。另外对可缓存的工具结果和 Prompt 做缓存相同订单号 1 分钟内不用重复调用模型。这些措施叠加起来能省下相当可观的成本。我见过一个团队因为忘了加缓存同样的订单查询重复调了十几次模型后来加了一层简单的缓存成本直接下降了三成。4. 完整实操一个“客服工单自动处理 Agent”的落地过程4.1 需求拆解与流程定义假设要给某公司的客服系统加一个“工单自动处理 Agent”。业务要求用户提交售后工单后Agent 自动提取订单号、问题类型和用户诉求查询订单信息生成处理方案如果方案涉及金额大于某个阈值推送给人工审批。先定义边界Agent 不直接操作退款不直接修改订单只负责生成建议和发起审批。这个边界能避免很多合规风险。然后定义状态流转每个状态都要明确输入、工具、输出和兜底。状态“submit”接收用户消息不做工具调用负责提取订单号和诉求信息不足则追问“classify”把订单文本送给意图分类器输出问题类型低置信度转人工“query_order”用订单号调用查询 API返回订单状态和金额查询失败转人工“solution”结合订单和问题类型生成方案建议无匹配方案转人工“approval”提交审批 API返回审批单号报错重试“done”输出最终会话结论。表格化之后整个流程一眼就能看明白。4.2 工具集实现与 Agent 编排实现三个工具每个工具都是统一接口。查询订单信息、查询商品说明书、提交审批单。我们写一个统一 wrapper统一做参数校验、超时控制和错误返回。class Tool: def __init__(self, name, schema, handler, timeout5): self.name name self.schema schema self.handler handler self.timeout timeout def invoke(self, params): validate_params(self.schema, params) try: result run_with_timeout(self.handler, params, self.timeout) return {ok: True, data: result} except TimeoutError: return {ok: False, error: timeout} except Exception as e: return {ok: False, error: str(e)}然后状态机在每个状态下调用模型模型返回一个工具调用编排层执行工具把结果返回给模型继续走下一步。工具调用后的模型再次生成需要正确的消息组织把之前的用户请求、工具调用、工具结果一并作为历史给模型否则模型会失忆。我们自己有一个固定的 messages 构造规则所有状态都走同一套逻辑减少出错的概率。4.3 异常场景处理与人工兜底线上最大的问题不是模型不会回答而是模型不确定时硬答。我们的策略是给 Agent 设一条“不自信”通道当模型置信度低于阈值或关键字段缺失或工具调用失败时不允许自行编造必须向用户请求补充信息连续两次失败就自动转人工。另外所有无法判定的事件都会写进一个人工队列。这个队列和 Agent 本身一样重要甚至更重要。线上运行后你会发现10%~20% 的工单最后需要人工介入这不是失败而是系统安全设计。生产级 Agent 的目标不是替代人工而是让部分简单问题自主解决复杂问题有序排队。人工队列的接口要和工单系统打通避免人工处理时还要把用户信息重新抄一遍。这个体验做得顺不顺直接决定业务方愿不愿意用这套系统。4.4 上线前的评估与灰度上线前我们整理了一个 1000 条历史工单的评估集。每条工单都有人工标注的目标动作比如应该查哪个订单、给什么方案。Agent 跑完后自动比对统计任务完成率、格式合格率、工具误用率、平均 Token 数和 P95 耗时。设好能够上线的阈值任务完成率 ≥ 90%格式合格率 ≥ 98%工具误用率 2%。达不到就继续调不要硬上。灰度一般分三阶段5% 流量跑两天看错误率和人工介入率然后放到 30% 跑一周观察成本最后全量。每个阶段都要有开关出了事一键切回人工流程。这个设计看起来繁琐但能在关键时刻救命。我们曾经在灰度阶段发现某个工具在高峰期响应特别慢如果直接全量大概率会把客服系统拖垮幸亏有这层开关。5. 高频问题与排查技巧实录5.1 常见问题速查表下面这张表我建议直接收藏都是真实线上环境里反复出现的问题。现象可能原因排查方向解决办法Agent 频繁调用无关工具工具描述模糊、Prompt 自由度过高看 trace 中被调用的工具和当时 user query精炼工具描述缩小每个状态的允许工具集模型返回 JSON 解析失败模型不支持严格结构化输出抓原始响应看解析失败的具体位置改用结构化输出接口或加二次修正和正则兜底线上成本突增缺少限流、缓存失效、模型循环调用看成本看板是否集中在某些用户/功能加配额、加缓存、设置最大步数上下文超长或模型卡顿把全部历史塞进 Prompt没有分层记忆统计请求的 Token 数和上下文长度做摘要压缩、窗口截断和按需检索模型输出与事实不符知识库缺失、Prompt 负面引导对比检索内容和模型输出增强 RAG 召回质量限制输出范围5.2 排查方法从现象到根因分享一个真实经历。有段时间我们的 Agent 在夜间集成环境频繁报错用户侧表现为一到晚上就卡住。一开始大家怀疑是模型服务商晚上限流后来通过 trace_id 定位发现夜间有批量任务触发了同一个工具该工具每次都要等一个外部接口响应超时时间设置过长导致线程池被占满。问题不在模型也不在状态机而在工具并发设计。排查顺序应该固定下来先看 trace 和时间线确定是哪一层再看请求参数和返回码最后做小样本复现。不要一看模型输出不对就改 Prompt那样往往掩盖真正的问题。我见过太多人把时间花在调整 Prompt 上结果问题出在缓存 key 写成了一样。先假设“模型没错”检查你的调用方式、数据、基础设施最后再回来看模型行为。5.3 避坑建议与个人体会最后说几点实操总结。第一先定义评估集再调系统。没有评估集你会被偶尔很好用的假象骗了。第二把 Agent 的自由度推到流程边缘。核心流程用状态机约束边缘的开放性问答才让模型自由发挥。第三人工兜底不是可选项。生产级系统必须设计模型失败后会发生什么的路径。第四成本监控从第一天就做等到月底账单出来再后悔就晚了。第五缓存和幂等是好朋友。工具调用尽量设计成幂等重复执行不会引发副作用。我个人实际做下来最值钱的经验是把 Agent 当成带概率的组件来对待而不是当成会思考的主脑。所有概率性的输出都要被工程确定性围住。这套工作流上线后客服团队的自动解决率稳定在七成以上人工只处理真正复杂的 Case团队也从被工单淹没变成了处理有价值的问题。生产级 AI Agent 工作流不是一个炫技的摆设它本质上是在模型能力之上补上工程系统该有的稳定和安全。只要这个骨架搭对了后续换模型、加工具、扩展场景都会顺畅很多。