前阵子有个做客服系统的团队来找我聊智能体项目,聊到一半对方冒出一句:“我们其实已经调通了大模型接口,工具调用也写了,但就是感觉整个Agent不太听话。”这句话我太熟了。很多团队对AI智能体的第一认知是“模型会自己规划、自己干活”,于是把开发重心放在API对接上,结果一进真实场景就出问题:要么任务稍复杂模型就开始绕圈,要么上下文一长就记不住前文,要么工具调用链路断了一环就全盘崩掉。我自己的项目也踩过这些坑,连着几次版本迭代后才理出一套相对靠谱的开发流程。这篇博客就是把这套流程拆开讲清楚,重点不是“调通一个Demo”,而是“让智能体在真实任务里稳定可用”。如果你是负责智能体落地的工程师、算法同学,或者正准备从聊天机器人往“会干活”的方向升级,这篇文章应该能帮你避开大部分弯路。
1. 第一步不是选框架,而是把任务边界掰开揉碎
1.1 先把“输入-输出-工具”三件事写清楚
很多团队做智能体,第一步就冲去选LangChain还是自己写循环,这是本末倒置。AI智能体和普通接口最大的区别在于:它是在一个循环里自主决策的。同一个提示词、同一个模型,如果任务边界模糊,行为就会飘忽不定。所以动手写代码之前,先把三件事写下来。
第一是输入边界。用户到底会以什么方式发起请求?是结构化表单还是自由文本?允许多长的上下文?允不允许用户上传文件?这里最容易被忽略的是“模糊表达”,比如一个数据查询智能体,用户可能说“看一下最近卖得怎么样”,这算不算合法输入?如果需要澄清,澄清问题的范围是什么?如果你不写清楚,模型就会在“猜用户意图”和“追问确认”之间随机切换,体验极其分裂。
第二是输出边界。终态输出是给一段总结文本,还是执行一系列动作?如果涉及多步骤操作,结果怎么汇总给用户?输出格式要不要固定?我见过一个项目,智能体负责生成报表,结果模型有时候输出Markdown表格、有时候输出CSV、有时候直接给一句“我建议你去后台看” —— 原因就是定义输出边界时只写了“回答用户问题”,没写“必须输出JSON结构的数据”。
第三是工具边界。这是最核心的。工具清单本身就是一种约束——它决定了Agent“能做什么”和“不能做什么”。这一步要逐个列清楚:每个工具的用途、输入参数、返回结构、可能的失败模式。不要等到编码阶段再想,因为工具边界的模糊会直接传染给模型的规划能力。工具描述写得不清楚,模型就经常选错工具,这不是模型的错,是定义没做到位。
把这三件事写清楚之后,再回头选框架、选模型,你会发现选择标准完全不同了。
1.2 给“不确定”留出口:兜底与澄清机制
任务边界再清晰,真实用户也总会抛出边界外的请求。这时候智能体的表现,决定了它是“助理”还是“废物”。
我的做法是给智能体预设三条兜底路径。第一是澄清路径:信息不足时,允许并鼓励模型发起追问,但追问次数要设上限,建议控制在1到2轮,再多就是在折磨用户。第二是降级路径:任务太复杂或者依赖链太长,允许模型拆解成子任务分步执行,而不是要求一步到位。第三是拒绝路径:超出现有能力或权限范围时,模型得学会说“这件事我做不了”,而不是硬编一个离谱答案。
这里有个很实用的技巧:在初始提示词里给模型一个“任务边界清单”,明确告诉它哪些场景可以直接做、哪些场景要澄清、哪些场景要拒绝。这不是多此一举——模型在边界清晰的环境下,规划成功率会高很多。不要指望模型“懂事”,要把懂事写进规则里。
1.3 从案例反推:一个客服智能体的任务边界文档长什么样
拿客服场景举例,一份可落地的边界文档大概长这样:
- 输入边界:用户咨询订单、物流、退款、发票四类问题。支持自然语言提问,但需先通过问题分类模块识别类别。上下文长度超限时,只保留最近两轮完整对话,更早内容做摘要。
- 输出边界:答案必须基于知识库检索结果或工单系统数据,不允许编造政策。退款类问题必须输出标准流程编号。所有回答语气使用中性客服风格。
- 工具边界:订单查询返回订单状态列表、物流查询返回节点轨迹、知识库检索返回带来源段落。三个工具独立调用,不互相依赖。
- 兜底路径:无法识别类别时追问一次;涉及改地址、催发货等高风险操作时引导转人工;用户反复追问同一问题时自动转人工。
这份文档写完后,智能体开发基本就变成了“把边界文档翻译成约束逻辑”,而不是无休止地调提示词。你会发现评测的时候也多了一把尺子——边界外行为不符合预期,算Bug,不是算模型发挥失常。
2. 模型与框架的选型:能力边界才是硬约束
2.1 模型选型:别只看跑分,要看工具调用和上下文长度
选模型这件事,市面上测评一大堆,但那些“通用能力跑分”对智能体开发的参考价值很有限。真正有参考价值的是这三项:工具调用的准确率、上下文长度与长文本稳定性、指令遵循的严格程度。
工具调用准确率怎么理解?模型需要从多个工具中选择正确的那个,并生成符合参数schema的调用请求。这个能力在基准测试里看起来都过得去,但放到真实任务里差异巨大——有的模型在“二选一”工具场景下表现不错,一旦提供七八个工具,就开始频繁选错或者生成缺失参数。所以选型阶段一定要拿自己的工具列表去跑一遍,不要直接信发布报告。
上下文长度也要特别警惕。很多模型号称支持几万token上下文,但实测下来,长上下文的“有效利用率”远低于宣传值。早期信息会被后续内容稀释,模型经常只盯着最近几轮对话。这也是为什么第4章我会强调上下文工程——选型阶段你至少要知道“模型在什么上下文长度下开始掉链子”。
指令遵循的严格程度就更隐蔽了。同样一个“按JSON返回”的指令,有的模型能严格输出结构化JSON,有的模型则偶尔夹带一两句解释。这类问题不影响Demo演示,但一旦接入生产,解析层就会频繁报错。我实测过的经验是:在prompt里加入“输出不得包含任何解释性文字”这类硬约束,然后用一组固定case去压测,能筛掉一大部分候选模型。
2.2 框架的Agent能力:自带编排不等于你有编排
很多框架宣传自己是“Agent框架”,支持规划、工具调用、记忆管理。这些能力确实存在,但有一个前提:框架给的是一套通用编排,而你的业务需要的是约束编排。
举个例子,某个框架提供了ReAct循环,模型会“思考→选工具→看结果→再思考”。Demo阶段很顺。但到了生产环境你会发现,这个循环可能跑50轮都停不下来,或者某一步工具调用失败后,框架只会机械地重试,不会根据失败原因调整策略。框架的Agent能力解决的是“有没有”,解决不了“合不合适”。
这时候就需要区分:框架负责什么,你负责什么。我的经验是框架可以负责模型调用、消息历史管理、基础的流式输出;但任务分解策略、工具调用的失败兜底、上下文的管理策略、以及最终答复的校验,这些必须由项目自己控制。把框架当作“基础设施”,不要当作“大脑”。
2.3 三种搭建路线,我实测下来的差异
现在市面上搭建智能体的路线大概三种:
第一种是直接用现成框架的开箱能力。适合需求简单、工具数量少、对可控性要求不高的场景,比如一个内部知识问答助手、一个单向流程的工具助手。优点起步快,缺点就是前面说的,深度定制会越来越难。
第二种是框架加策略定制。这是大部分生产项目的选择。框架处理底层模型调用和消息管理,但任务分解、工具校验、重试策略、上下文摘要等关键逻辑在应用层自己写。这种模式灵活度和开发效率的平衡最好。
第三种是完全自研编排。适合工具链路极其复杂、对延迟和成本有强约束、或者需要深度控制每一步行为的场景。缺点很明显:开发量大、可观测体系要自己搭。我见过一些公司最后不得不从框架迁到自研,大多数原因都是框架的抽象层掩盖了太多细节,出了问题无从排查。
三种路线没有绝对的优劣,但有一个通用的判断标准:你的智能体本质上是一个“状态机”,还是一个“自由聊天机器人”。前者建议自研或深度定制,后者直接开箱用。
3. 把“规划-调用-反思”变成可见、可控的流程
3.1 主流程的状态机设计
很多智能体开发者的误区是:把Agent流程写成一个大循环,“不断让模型预测下一步”。这种写法的优点是灵活,缺点是失控。生产环境必须要有一个明确的状态机。
我常用的状态机设计是这样:
- receive:接收用户输入,做预处理,比如检查长度、过滤敏感词、识别意图。
- plan:让模型做任务分解。注意,这里的分解不是一次性把所有步骤都列出来,而是先列一个粗粒度执行计划,每步执行完再决定下一步。
- act:执行工具调用。调用前要校验参数合法性,调用后要校验返回结果是否吻合预期。
- observe:把工具返回结果整理成模型能理解的摘要。这里很关键,不要把原始返回一股脑塞进上下文,要抽取关键字段、做格式化的说明。
- reflect:让模型检查当前状态——结果是否达到用户目标?是否需要调整计划?是否需要修正上一步的偏差?
- respond:输出最终答案,或发起澄清追问。
这个状态机看起来繁琐,但每一步都对应着一个可控的观察点。模型在哪一步开始胡来,日志里一目了然。没有状态机的大循环就像没有红绿灯的十字路口,偶尔畅通,迟早堵死。
3.2 工具层设计:描述、参数校验与依赖关系
工具层是智能体的“手脚”,而工具描述就是给模型看的“使用说明书”。很多团队工具描述写得太随便,比如“get_order_info”,描述只有一句“获取订单信息”。这种描述下模型经常不知道该传什么参数、不知道返回结构、不知道失败时怎么处理。
我自己的工具描述模板长这样:
- name:工具名,语义清晰,比如“查询订单物流轨迹”
- description:说明这个工具解决什么问题、在什么场景下使用、不要在什么场景下使用
- parameters:参数列表,每个参数要写明类型、取值范围、是否必填、示例值
- returns:返回结构的说明,包括关键字段、可能的状态值
- error_handling:返回异常时模型应该怎么处理,比如换一个工具、还是直接告诉用户查不到
参数校验是另一个重要环节。模型生成的参数偶尔会有幻觉,比如把日期格式写错、把ID拼错。不做校验就调用真实接口,轻则返回空数据,重则触发脏数据写入。所以工具调用前必须有一层硬校验,校验失败时返回明确错误信息,让模型重写参数。
工具之间的依赖关系也要在流程层面管理。比如“先搜索再抓详情”“先查权限再执行操作”。这种依赖关系不能指望模型每次都能领悟,要写在编排逻辑里。工具调用顺序本质上是你业务的流程规则,模型只是执行者,规则制定者必须是人。
3.3 反思与重试:给模型一次“改错”的机会
到了act和observe阶段,你一定会遇到工具调用失败、结果不匹配预期的情况。这时候究竟直接报错给用户,还是让模型反思修正一下?我的经验是:给一次追加的反思机会,但要设硬边界。
反思的重试机制大概是这样的。某次工具调用返回空数据,模型先看错误信息,判断是不是参数问题、是不是搜索范围太窄、是不是工具选错了。如果是参数问题,可以重新生成参数再调一次;如果是工具选错,就换工具;如果连续两次都失败,就停止重试,告诉用户“暂时查不到结果,可能原因如下”。
这个机制能解决大量真实场景的偶发失败,但要注意三个约束。第一,重试次数必须限制,建议最多2次,防止模型陷入死循环。第二,总步数必须限制,用一个计数器追踪整个对话中的工具调用轮数,超过上限就强制收尾。第三,反思日志要记录,这样你能复盘模型每次重试的决策质量。
我见过最严重的死循环事故,是某个智能体在重试时一直生成相同参数、调用相同工具、得到相同失败结果,循环了20多轮才被超时机制打断。从那以后所有项目都加了“相同失败不超过2次”的兜底判断。
4. 上下文工程:记忆比背会多少资料更重要
4.1 短期记忆与上下文窗口的博弈
AI智能体的产品形态决定了它通常要多轮对话,但把每轮对话全文塞进上下文,很快就把模型窗口撑爆。这不是成本问题,是质量问题——上下文越长,模型对早期信息的感知越弱。
我推荐的做法是分层管理短期记忆。最近的1到2轮对话,保留完整原文;更早的内容,抽取关键事实形成摘要;再早的内容,只保留状态字段,比如“用户订单ID”“用户所在城市”“当前任务进度”。这个策略能让上下文窗口的利用率大幅提升。
具体实现上,可以用一段固定结构的状态信息跟随每次请求。比如:用户状态块包含用户ID、当前会话目标、已确认信息、待执行动作、历史摘要。模型每次决策前先读这个状态块,再读最近对话,而不是翻开全部历史。对用户来说,智能体的“记忆力”反而变得更强了。
4.2 长期记忆:向量库不是万能检索器
很多团队一听到“智能体记忆”,第一反应就是上向量数据库。但长期记忆这件事,“存什么”比“怎么存”重要得多。
向量检索适合的是“语义相关但内容不确定”的回忆场景,比如“上次我让你查的那家公司的融资情况”。但用户的长期偏好、历史决策记录、已完成任务的状态,这些结构化信息更适合用实体化存储,比如存成用户属性表、偏好标签、任务历史表。你完全可以混合使用:结构化存储管“事实”,向量库管“语义检索”。
还有一个很容易被忽略的问题:长期记忆的写入不能全量塞。用户随口说的一句话、任务中间的一个临时状态,都不值得写进长期记忆。写入策略要靠规则来约束,比如“用户明确表达的偏好”“用户确认过的关键信息”“任务完成后的结果摘要”这三类才值得沉淀。写得太多,噪声会盖过信号,检索到的内容反而干扰模型判断。
4.3 上下文压缩与重写:最后的兜底手段
即便做了分层管理,上下文还是会膨胀。尤其是涉及多步工具调用时,每一轮的工具返回都会占用不少空间。这时候需要在每次工具结果返回后做一个压缩改写。
我常用的方法是这样:工具返回原始JSON可能几千字,但真正对后续决策有用的可能只有几个字段。我会用一个压缩模板,把原始结果转成一段精炼的文本描述,只保留关键信息。比如查询订单列表,压缩后只保留“同时满足条件的订单共3个,最近一单是订单A,状态为已发货,预计明天到达”。模型后续决策只需要这段文本,不需要看原始结构。
有些项目还会进一步做“上下文重写”——把多轮零散信息整合成一段连贯的任务状态描述。比如用户先说了地址,又说了日期,再问了价格,系统可以在下一轮把这三条信息合并成一条结构化状态,而非让模型自己去历史里翻。上下文管理做到这一步,智能体的稳定性会有一个质的飞跃,很多“忘事”“糊涂”的问题会直接消失。
5. 评测是智能体开发里最容易糊弄、也最不能糊弄的环节
5.1 为什么单轮问答评测在这里会失真
做过聊天机器人的团队,通常习惯用单轮问答去评测模型效果。这个习惯在智能体项目里会害死人。为什么?因为智能体的核心能力是“多步决策”,不是“单轮应答”。同一个任务,可能涉及三次工具调用、一次反思、一次追问澄清。单轮评测无法覆盖这些行为链路。
举个例子,一个评测case是“帮用户查询最近的订单物流”,如果只看最终答案,可能答案是准确的;但你无法知道模型是不是问了一堆废话、是不是多调用了一次不必要的工具、是不是在信息不足时做了一次没有必要的猜测。这些“过程问题”单轮评测完全看不见。
所以智能体评测至少要分三个层次:最终结果层、行为链路层、资源消耗层。结果层看答没答对,行为链路层看决策过程合不合理,资源消耗层看调用轮数、token消耗、耗时是不是在可接受范围。三层叠在一起才能反映一个智能体的真实水平。
5.2 构建评测集的三个层次
评测集怎么建?我的经验是至少分三个层次采集。
第一层是标准任务集。也就是最常见的正常任务,比如“查订单”“问政策”“提交工单”。数量要多,覆盖常见变体。这一层用于判断系统的“底线能力”。
第二层是边界任务集。包含模糊表达、信息缺失、多条件约束、需要追问澄清的场景。比如用户只说“我那个东西还没到”,没有任何订单号、收件人信息,模型应该判断出需要追问哪些字段。这一层考验的是对话管理与澄清策略。
第三层是干扰与压力集。包括语义噪声、用户反复改需求、多轮中途切换话题、超长上下文继续追加提问。这类case主要测试系统会不会崩溃、会不会忘事、会不会在用户已经放弃时继续固执地执行原计划。
评测集规模上,我建议不要盲目追求数量。500到1000个精心设计的场景,比1万个随意采集的case有用得多。智能体的评测问题通常不是数量不够,而是场景覆盖不系统。
5.3 关键指标怎么取:任务完成率、工具调用准确率、追问率
做了评测集之后,再看指标。这里我建议优先关注四个核心指标:
任务完成率是最终结果层的核心指标,定义要严格——用户目标是否完全达成。部分达成不算完成,必须走完整个链路且用户目标被满足才记一例。
工具调用准确率是行为链路层的指标,看的是:被调用的工具是不是正确工具、参数是否合理、有没有多余的、无意义的调用。一个系统如果最终答对了但乱调了很多工具,说明规划能力有隐患。
追问率反映澄清策略是否合理。追问率过低,模型可能一直在瞎猜;追问率过高,用户会被烦死。具体阈值要看业务形态,但必须观察这个指标的波动。
平均轮数和平均耗时是资源消耗层指标。智能体任务通常在3到8轮之间完成是合理的,超出则说明规划或反思策略有问题。耗时则直接关乎用户体验,模型思考过久用户是能感知到的。
这些指标不能只在离线评测里看,上线后要持续在线监控。模型的输出可复现性本来就弱,指标波动一次很正常,持续偏移就必须排查原因。
5.4 可观测性:把思考过程变成可排查的日志
智能体比传统接口难排错得多,因为它每一步都依赖模型的内部决策。这个决策如果不落盘,出了Bug就只能靠猜。所以从第一天开发起,就要把可观测性搭好。
我要求的日志字段包括:用户输入的完整记录、模型每一步的规划输出、选中的工具与生成的参数、工具的实际返回与错误、重试次数与重试原因、每一步消耗的token数、以及最终输出的生成链路。这些日志并不仅仅用于排错,也是评测集回放、提示词迭代、模型版本切换对比的基础数据。
日志记录时有一个细节:模型思考过程中间可能很长,直接塞进日志会很难读。建议每个步骤生成一个结构化事件,包含阶段名、输入摘要、输出摘要、耗时和关键决策点。这样排错时能像看流水线一样逐段检查,而不是翻一坨文本找线索。智能体的调试体验好坏,很大程度就取决于这一步做得好不好。
6. 从Demo到生产:上线前的几次“事故”教我的事
6.1 安全问题:提示词注入是真实存在的
智能体的工具调用能力放大了安全风险。有人通过输入恶意指令,试图诱导模型绕过约束执行额外工具操作。传统接口拿到的输入是参数,智能体拿到的输入是“可能影响行为的内容”,这就是本质区别。
生产环境我建议做四件事。第一,严格限制工具的权限范围,每个工具只开放最小必要权限,绝不能暴露“执行任意代码”这类的危险能力。第二,对用户输入做检测,识别常见的提示词注入模式,识别到就拦截到兜底流程。第三,关键工具调用前必须通过参数校验层,不允许直接将用户原文透传给底层接口。第四,所有工具调用保留审计日志,事后可追溯。
很多团队觉得提示词注入是“演示环境里才会发生的攻击”,实际上真实用户中也会出现,有些是无意中触发的,有些是恶意构造的。不管哪种,都要保证智能体不会执行超出预期的操作。
6.2 限流与超时:模型慢的时候,你的系统也要能活
模型接口的延迟不像普通API那么稳定。高峰期变慢、偶发超时、返回格式异常,这些在生产环境都会遇到。智能体一个任务里要多次调用模型和工具,只要一次超时,整个任务就卡住。
我的建议是三层保护。第一层是接口超时与重试,模型调用设超时上限,超过则重试一次,再失败就给用户返回“服务暂时繁忙”。第二层是任务级超时,整个智能体任务从开始到结束设置总时限,比如60秒,超时则终止并返回当前已完成的结果。第三层是并发限流,按模型API的配额和下游工具的承载能力,限制同时运行的智能体任务数,防止雪崩。
还有一个小技巧:工具调用的耗时往往大于模型单次调用。如果某个工具很慢,可以考虑异步化处理。比如数据查询类工具先提交任务、再轮询结果,最后统一汇总给模型。这样整体体验会好很多。
6.3 发布策略不冒险:小流量灰度与对抗样本回放
上线发布这里,我想单独说一点。智能体系统不像普通功能那样“发布后就稳定”,同一个模型版本在真实用户输入上随时可能出现新问题。所以发布策略要格外保守。
我的做法是:新版本智能体先在小流量上灰度,并行对比旧版本的任务完成率和用户反馈;每天回放灰度期间的日志,把异常case加入评测集;确认新版本在评测集上不劣化之后,再逐步放量。这听起来麻烦,但实际执行下来能拦截大量“评测集里看不出来”的坑。
印象最深的一次事故是,某个版本换了一个模型之后,单轮问答评测分数涨了,工具调用的准确率也涨了,但真实用户反馈变差了。回放日志才发现,新模型在“多轮追问的耐心程度”上明显下降,用户稍微表达模糊就立刻给结论,显得不靠谱。这种问题在静态评测集里很难覆盖,却对生产体验影响巨大。所以灰度日志的回放,要当作日常开发的一部分,而不是上线前的临时动作。
我在多个项目里实践下来的体会是:AI智能体的开发流程没有太多“秘密武器”,本质是把不确定性变成可控流程。任务边界定清楚、状态机搭起来、工具层做规范、上下文管明白、评测和日志做到位,剩下的就是持续迭代。不要试图第一个版本就做出完美的Agent,先把骨架立住,把每个环节的可观察点都埋好,后续加能力、换模型、调提示词,都会变得有据可依、有迹可循。这条路走到后面,你会发现自己做的其实不是“调模型”,而是在搭一套稳定的决策系统。