
从一次翻车Demo说起。前阵子我给一个内部工具做Agent化改造目标是让模型自动查订单状态、补发通知、按规则升级异常单。演示前我信心很足结果当着使用方负责人的面Agent第一轮就栽了——工具调用返回的JSON被截断参数嵌套错位整个流程卡死在中间态。我一边手忙脚乱修数据一边解释“模型输出有点随机”场面相当尴尬。那次之后我花了很长时间重新审视Agent开发这件事。结论是Agent开发真正的门槛不在模型而在编排。模型再怎么强也只是个会犯错、会遗忘、会钻牛角尖的“脑力劳动者”你要设计的不只是一段提示词而是一整套让这个“脑力劳动者”能干活的流程、边界和纠偏机制。这篇文章不聊概念就聊我实际做下来看到的门道给正在做Agent项目、或者准备评估Agent能力的团队做个参考。1. 为什么说Agent开发不是写程序而是组织一次“委托协作”1.1 一次翻车Demo给我的三个冲击那天的场景其实是标准的多步任务查询订单状态、判断是否需要补发、给客户发送通知。我事先把系统提示词写得非常详细工具描述也做了结构化模板自认为万无一失。结果同一个任务跑三次三次结果都不一样第一次调用成功模型正确解析了订单号第二次同样的输入模型把参数名从order_id换成了orderId工具层没认出来第三次更离谱模型连续两次调用了同一个查询工具参数一模一样纯粹空转。这件事给我的冲击主要有三个。第一模型不是程序它不会“给定相同输入永远给出相同输出”同一个提示词在不同轮次可能有细微波动这种不确定性是Agent开发的底层前提。第二提示词写得再详细也只是降低了出错概率并没有消除出错可能你必须在外层做兜底。第三人工“调通一次”和“工程可靠”是两回事一两个Demo成功不能说明系统可用你需要用数据去度量它。后来我把这次事故当作团队内部的一个反面教材反复讲Agent开发里最危险的心态就是把模型当作一个“听话的函数”。模型不是函数它是个有主见但也会马虎的协作者。1.2 传统编程与Agent开发的本质分野传统编程的世界是确定性的if/else、循环、数据库事务给定输入期望输出基本固定出错了能通过日志精确回溯。你写的每一行逻辑都是确定的因果关系。Agent开发不一样。模型在每一步都是“概率性决策”它可能在两个同样合理的行动之间摇摆可能因为上下文太长而忘掉最初目标也可能在一个已经失败的选项上反复重试。代码层面的if/else管不住这些行为因为模型的“输入”是自然语言输出也是自然语言或半结构化数据边界是模糊的。我常用一个类比来解释这件事传统编程是你在骑自行车每个动作精确可控制Agent开发是你给一个实习生交代任务告诉他目标、给他工具、告诉他哪些事情绝对不能做然后放手让他干。实习生的好处是会变通坏处是你得随时准备纠偏、复查、处理他交回来的“半成品”。所以Agent开发的本质不是“写逻辑”而是“组织一次委托协作”。你的核心任务是定义清楚目标是什么、有哪些工具、每一轮决策需要什么信息、什么情况下停下来、什么情况下必须回到人类这里来。换句话说代码管规则模型管判断。2. Agent的心智模型用“任命高管”的思路设计系统2.1 LLM Agent的五个核心组件拆解我把一个完整的Agent系统拆成五个组件做任何Agent项目都可以拿这个框架对一下看看自己漏了哪块目标任务定义通常写在系统提示词里。目标要明确但不能把步骤也写死。比如“查询订单状态并处理补发”比“先调接口A若返回B再调接口C”更合理因为模型需要保留判断空间而步骤很可能在实际执行中需要调整。规划器决定“下一步做什么”。常见有ReAct循环推理-行动-观察和Plan-and-Execute先列计划再执行。规划器决定了系统是走一步看一步还是先把方案定了再动手。工具集模型可调用的外部能力包括API、数据库查询、代码解释器、搜索等。工具集是Agent的“手和脚”也是出错率最高的地方。记忆短期记忆是当前上下文窗口长期记忆可以是向量库、摘要缓存或外部数据库。记忆设计不好Agent会变成“金鱼”。护栏权限白名单、预算上限、步骤数上限、敏感操作人工审批等。护栏是Agent系统能不能上生产的生死线没有护栏的Agent只配活在Demo里。这五个组件里目标决定方向规划器决定策略工具决定能力边界记忆决定连续性护栏决定安全性。任何一个组件缺位系统都能跑起来但跑不远。2.2 开发者的工作重心定协议而不是写逻辑很多刚接触Agent开发的同事喜欢在系统提示词里穷举各种情况“如果用户说A你就做B如果说C你就做D。”这种写法的产出是一个无比臃肿的提示词看起来面面俱到实际上模型根本记不住而且一旦场景超出枚举范围反而会无所适从。我的经验是提示词负责定义角色和目标代码负责定义规则。你要把主要精力放在“模型与工具之间的协议”上。协议至少包括这几个问题工具描述怎么写参数类型、必选可选、枚举值、示例值都要结构化地写清楚。模型对工具描述的理解直接决定了它能不能正确调用工具。工具结果怎么返回返回结构要固定比如{ status: success, data: {...} }不要让模型去解析一段自由文本。出错怎么上报工具异常应该有明确的错误码和错误消息模型看到错误之后才能做出正确的下一步决策比如换个参数重试或者放弃并上报。什么情况下停止成功条件、失败条件、最大步数都要在协议里定义清楚否则Agent会一直“努力”下去。举个例子一个查询工具的描述我是这样写的工具名query_order 功能根据订单号查询订单状态 参数 order_idstring必填订单编号格式为 14 位数字 include_itemsboolean可选默认 false是否返回订单商品明细 返回 statusstringsuccess / not_found / error dataobject订单状态、更新时间、物流信息工具描述写得好不好直接决定模型调用的准确率。我之前测试过把参数描述从一行简单文本改成带有类型和示例的结构化描述后同一批测试用例的工具调用正确率能从76%提升到91%而且这还是在模型版本、提示词完全不变的情况下。协议设计是Agent开发里投入产出比最高的环节可惜大多数人把精力都花在提示词上了。3. 框架选型与模式取舍从单Agent到多智能体3.1 三种模式的定位差异Agent开发在架构上通常有三种模式很多团队一开始没想清楚就上了最复杂的后面维护成本非常高。这三种模式我都实际跑过先说结论能简单就简单能用工作流解决就别上多智能体。单Agent模式一个模型循环负责全部决策每一步决定调用哪个工具、如何解读结果。优点是实现简单、容易排查缺点是单个模型要承担所有认知负担任务一复杂就容易顾此失彼。我用下来觉得适合步骤不超过五六步、工具不超过十个的垂直场景。工作流模式把流程预先编排成固定步骤DAG或者状态机只在特定节点让模型做决策。比如“先识别意图再抽取参数再查询数据最后由模型生成回复”。这种模式的稳定性和可调试性最好因为流程的骨架是确定的模型的自由度被限制在特定环节。缺点是灵活度低不适合需要临场发挥的任务。多智能体模式多个模型角色协作比如规划者、执行者、审查者各自有独立的提示词和工具权限通过某种通信协议交换信息。这种模式的想象力上限最高但复杂度也最高角色之间可能互相误解、上下文重复消耗、成本指数级上升。我的判断是只有当任务本身真的需要“分工协作”时才值得用比如需要一边搜索资料一边做对比分析的场景。3.2 选型三原则面对这三种模式我是用三个原则来判断的复杂度决定分工。任务越复杂越需要拆角色。但如果一个单Agent能跑下来的任务硬拆成三个Agent只会徒增成本和不稳定性。我见过一个客服项目早期用多智能体做意图识别和情感分析结果两个角色之间互相覆盖最后改回单Agent加工作流效果反而更稳定。容错成本决定护栏强度。任务出错代价越高越要把决策权交给代码和人工。比如涉及支付、法务、对外承诺的操作我的建议是模型只负责生成“建议动作”由代码层或者人工审批确认之后再执行。之前团队做过一个自动回复项目凡是涉及赔偿金额的回复一律设置了人工审批门槛这个设计后来避免了好几次低级事故。迭代速度决定抽象程度。项目早期别急着引入花哨框架。先用最原始的“写死循环 提示词”跑通核心链路验证业务效果再逐步抽象。框架只是解决基础设施问题Agent的策略和协议设计始终在你自己的手里别把框架当万能药。3.3 框架层的能力对比我陆续试过几类主流的Agent开发框架简单说下体感不点名具体产品你可以对照自己的场景来判断框架类型适用场景优点缺点编排型框架需要深度定制流程、自控工具链的团队灵活度高可完全控制每个环节生态相对成熟接入模型和工具方便胶水代码多很多功能要自己实现学习成本高抽象层次复杂对话型工具聊天机器人、客服系统等以对话为主的场景上手快自带会话管理和多轮上下文处理体验好不适合复杂业务编排在执行多步工具任务时能力偏弱低代码平台快速原型验证、非技术团队搭建简单Agent拖拽配置见效快内置常用插件和模板定制能力受限生产环境下的可观测性和权限控制往往不够细我的核心建议是框架只是给你提供了“进程、调用、解析”这些基础设施真正决定Agent上限的是你的目标定义、工具协议、记忆策略和护栏设计。选框架的时候就问一个问题它能不能让我方便地记录每一步的调用链路、控制工具白名单、设置步数和成本上限能就值得用不能再花哨也别选。4. 踩坑实录工具调用、幻觉与上下文失控的完整排障链路4.1 工具调用的“格式抖动”是最普遍的翻车点做Agent开发第一个高频翻车点永远在工具调用。模型需要输出一个结构化的“函数调用指令”比如 JSON 格式的参数但这个输出是概率性的偶尔就会出错。我实际遇到的问题有这几类JSON被截断输出到一半就停了可能是生成了过长的参数或嵌套结构字段缺失或参数名漂移模型把user_name写成username工具层就认不出来参数类型错误定义的是数字类型模型给了一个字符串幻觉工具名模型编造了一个不存在的工具名或者是把两个工具的名字拼接在一起。这些问题非常磨人因为不是每次都出现而是在特定输入、特定上下文长度下偶发。排查这类问题我的链路是这样的先记录原始响应。不要只看最终结果要把模型每一步的原始输出包括原始工具调用、原始错误完整记录下来。没有完整的trace这种随机性问题根本无从下手。对比失败案例的共同特征。把几十条失败日志放在一起看找规律是不是所有失败都发生在上下文超过一定长度之后是不是集中在某个特定工具上我遇到过一种情况凡是参数里出现长文本描述JSON截断率就明显升高。启用平台的强制工具调用机制。现在很多模型支持“强制调用某个工具”或者“结构化生成”能显著降低参数格式错误。如果你的模型平台支持优先用别裸写提示词去约束格式。加一层解析与校验。在模型输出和业务逻辑之间必须有一层代码做JSON修复和字段校验不符合协议的直接要求模型重新生成而不是把脏数据传给下游。这个校验层是Agent系统的“安全带”。我还试过一种双步法先让模型输出“意图”字段比如“查询订单”再根据意图输出“参数”。拆分之后参数生成的上下文更聚焦格式抖动的概率确实下降了但代价是一次任务多了一次模型调用成本和延迟都有上升。要看你的场景到底更在意准确率还是响应速度。4.2 上下文窗口的气球效应第二个坑是上下文管理。Agent执行任务时每一步的工具结果都会追加到上下文里上下文越来越大模型的理解力反而在下降。我把这个现象叫做“气球效应”气球吹得越大模型越容易漏掉最原始的目标。最典型的场景是长任务。比如一个数据分析Agent需要连续查询十几张报表每张报表返回几十行的JSON。查完第三张的时候模型还能准确记住目标到第七张它已经开始把前面报表的字段跟后面的指标混淆到第十二张它甚至会“忘掉”最初的分析维度产出跟目标无关的内容。我的应对方案有三个滑动窗口只保留最近N轮对话和工具调用结果更早的内容自动丢弃。这个最简单粗暴但要注意监督式任务不能丢关键上下文所以往往要配合下面两个方案。结构化摘要工具结果不要原文塞进上下文而是先经过一段摘要逻辑转成只包含关键字段的精简格式。比如查询订单列表200行结果可能缩成“最近三笔订单金额分别为500、320、750其中一笔已发货”。这个做法让上下文占用大幅下降模型决策时反而更聚焦。长期记忆外置需要长期跟踪的信息比如用户偏好、项目历史放到外部向量库或数据库里只在决策需要时检索出来注入上下文。我给自己的原则是上下文里只放“为当前决策服务”的信息不放流水账。模型不是数据库它的上下文窗口是推理工作台不是仓库。4.3 循环死锁Agent为什么回不到正轨第三个坑是循环。模型会非常执着地重复同一个动作特别是在面对失败时。我见过一个客服Agent在查询物流信息返回“接口超时”之后居然连续七次用同样的参数重试同一个接口直到步数上限被打满。这不是模型“傻”而是它在缺乏新信息的情况下只会重复尝试已知的行为。这里你要明白一个本质问题模型没有真正的“全局视角”它每一步只看到当上下文里的信息如果重试结果一直是失败它不知道“换一条路”而不是“再试一次”。所以解决方案不能放在提示词里要放在代码层设置最大步数和单一工具最大调用次数。我在项目里让模型每次最多连续三次调用同一个工具超过后强制进入“换策略”或“上报人工”分支检测到相同工具相同参数时自动打断。代码层维护一个“最近调用指纹”集合发现完全重复的调用就返回一个错误提示让模型知道这条路不通改用Plan-and-Execute模式。让模型在开始时先列出执行计划再逐步执行而不是每次临场决策。这种方式能减少因“不知道接下来做什么”而原地打转的概率。其实循环死锁的本质不是模型能力问题而是你没有给模型提供“此路不通就换路”的机制。把重试策略从模型手里收回到代码里这个问题就能基本解决。4.4 最小化复现排障唯一可靠的路径Agent项目的Bug和传统项目的Bug有一个本质区别不可稳定复现。同一个输入这次跑通了下次可能失败。这导致很多人一遇到问题就改提示词改完又不知道到底有没有用纯靠碰运气。我的做法永远是最小化复现。每接到一个线上失败案例先做这几步把失败的完整链路记录导出来包括系统提示词版本、模型版本、模型原始输出、工具调用入参和结果用固定的模型参数温度设为0在测试环境重跑同一条用例确认能否复现如果不能复现就尝试改变一个变量比如去掉上下文里的某段赘余、调整工具描述措辞、或者缩短工具返回结果直到能找到“触发条件”找到触发条件后修复一个问题再用全量回归集跑一遍防止修了A坏了B。这种排查方式很费时间但它是唯一可靠的路径。我在这个项目后期建立了一个“失败案例库”每一条都带着原始trace和触发条件每次改完提示词或升级模型版本都要拿这批案例回归。这个案例库后来成了团队最重要的资产之一比任何提示词模板都值钱。5. 把不确定性关进笼子Agent项目的工程架构实践5.1 推理层与执行层的两个世界架构上我坚持把Agent系统拆成两个世界推理层和执行层。推理层是模型做决策的地方允许模糊、允许概率性、允许犯错的余地。执行层是代码和API运行的地方要求精确、要求校验、要求可重试。模型不应该直接去操作数据库或调用外部系统而应该输出“指令”——一段结构化的描述比如“查询订单号abc123的状态并确认收货地址”。代码层负责解析这段指令、做权限校验、调用真正的API、把结果转成结构化数据返回给模型。有人可能会觉得这样多此一举。但实际项目中这个分层救了不知道多少次。一层是把模型的自由裁量权限制在“提建议”的范围内真正动手的是确定性的代码二层是所有的敏感操作比如支付、转账、删除都可以在这层强制加人工审批。模型可以建议“给用户退50元”但真正执行退款的是一道带着审批标记的代码调用。模型再厉害也碰不到钱。这个设计我用一句话总结CEO可以做决策但付款必须走财务流程。5.2 状态机加LLM的混合编排我见过不少团队做完Agent后流程控制完全靠模型的自然语言输出整个系统的运行轨迹就像一锅粥。我的建议是用状态机管骨架用LLM管决策。状态机负责定义任务的合法状态和转移条件LLM负责在某个状态下选择下一步动作。举个例子一个工单处理Agent我定义了这样几个状态状态说明状态转移由谁决定pending任务创建待分发代码自动按规则分发processingAgent执行中代码控制限制步数tool_waiting等待工具返回代码控制超时自动处理human_approval需要人工审批代码触发人工完成后放行done / failed / cancelled终态代码判断或模型上报每个状态之间的“合法转移”是代码写死的模型只能在当前状态下选择可执行的动作。比如在processing状态下模型可以调用工具查询数据但不能直接跳到done必须满足代码定义的完成条件。这样整个系统就有了一个“剪枝”机制模型再怎么自由发挥都逃不出你画的笼子。这套混合编排的调试体验比纯Agent自主循环好太多了。出了问题你可以直接看状态机停在哪个状态、是哪一次转移决策导致的而不是在几十轮对话日志里大海捞针。5.3 数据模型、权限与预算的安全设计Agent项目里的安全设计绝不是“模型不做危险的事”而是“危险的事根本到不了模型手里”。我做项目时维护这样的基础设计工具白名单每个Agent绑定一份工具清单不需要的工具一律不在提示词里出现接口层再做一层校验。不加白名单的话模型一旦幻觉出一个工具名可能直接撞上真实接口这是事故源头。用户级权限每个用户的权限在工具层校验不能信任模型输出的用户身份。模型可能会在上下文里看到用户A的信息然后错误地用它去执行用户B的查询。工具层要强制校验“当前会话对应的用户”与“被操作对象的所有者”是否一致。预算控制每一个Agent任务都要设置费用上限、步数上限、token上限。模型本身没有成本意识它不会想着省着点用。我在项目里设了三层每步计费、每任务封顶、全局并发限流超了就自动熔断回到人工流程。敏感操作审批涉及支付、退款、对外发布、改账号等操作模型只能生成“建议动作”由代码层生成审批单人工确认后才执行。这个机制会牺牲一些自动化率但换来的是可追责、可解释。数据模型方面我用四张核心表记录一切任务表task、步骤表step、工具调用记录表tool_call、人工审核记录表approval。每一条Agent行为都有案可查这既是排障的基础也是背锅的时候能说清楚问题的底气。5.4 可观测性日志、链路追踪和成本仪表盘黑盒系统必须有白盒运维手段。Agent项目的可观测性比传统项目更重要因为它的行为是概率性的不在运行期记录足够的信息事后根本无从分析。我给每个Agent请求设计的标准日志包含系统提示词版本、模型名称与参数、模型的完整输入输出原样保留不做截断、工具调用列表每个工具的入参、出参、耗时、费用、状态转移记录、最终结果和人工修改记录。日志全部带trace_id一条任务的全过程可以完整串起来。成本仪表盘是另一个必需的运维工具。我做过一个Agent单任务平均成本从早期的0.8元降到0.3元怎么做到的就是靠仪表盘发现“模型在工具调用失败后反复重试白白消耗了大量token”。后来加了重试限制成本立刻降下来。没有成本仪表盘这种钱就无声无息地烧掉了。可观测性不是“出了事再上”而是项目第一天就要有。因为Agent项目的Bug是概率性的比如在测试环境跑50次才出现一次如果没有trace复现和修复基本无从谈起。6. 评测与迭代Agent项目最难的是“觉得它已经够好”6.1 评测集建设比调Prompt重要十倍Agent开发的另一个核心工作是建设一套能代表真实场景的评测集。我吃过一个很大的亏早期项目开发时沉浸在Demo里觉得对话流畅、工具调用正常功能应该是能用了。结果放到真实用户手里各种奇怪的输入扑面而来成功率骤降到三成以下整个项目直接返工。现在我的做法是每做一个Agent第一件事不是写提示词而是先整理评测集。评测集至少要覆盖三类场景正常场景代表大部分用户的主流请求占评测集的60%左右边界场景输入格式奇怪、语义含糊、需要澄清的情况占25%左右异常场景工具失败、数据缺失、需要安全兜底的场景占15%左右。异常场景的来源有三个线上失败案例、客服反馈、自己脑补的风险点。每条评测用例都要人工标注“期望结果”不只是期望的最终答案还包括期望的工具调用路径。注意最终答案对但工具调用路径错乱的用例也要算失败因为路径是判断Agent逻辑健康度的关键。6.2 四个核心指标判断健康度有了评测集就要用指标来衡量Agent的健康度。我自己看四个核心指标指标含义我的建议标准视业务而定任务成功率完整跑通且结果正确的比例核心业务流程不低于90%工具调用有效率真正推进任务的调用占总调用的比例建议高于70%偏低说明模型在空转或走弯路平均步数与延迟完成任务的平均模型调用次数和总耗时步数增加意味着不确定性上升要关注单任务成本模型token费用 工具调用费用的均值设定封顶防止失控这四个指标不是孤立看的。比如工具调用有效率低往往意味着工具描述不清楚、或者上下文里有干扰信息步数激增往往意味着模型在做无效尝试。每个指标都能导向一个具体的优化方向而不是“凭感觉调提示词”。6.3 回归测试与灰度发布Agent模型升级是双刃剑。升级模型版本后Demo效果可能变好但整体成功率可能反而下降因为模型的行为在长尾场景可能完全不一样。我遇到过一次升级模型版本后顺畅场景的回复质量明显提升了但在一批口语化长尾请求上工具参数抽取成功率掉了二十个百分点。最后是评测集的回归测试抓住了这个问题否则直接上生产就是事故。所以我的上线流程是严格灰度跑评测集对比新旧模型在同一评测集上跑一遍对比四个核心指标不达标就不上。小流量灰度先切5%的流量到新版本观察真实场景的成功率、成本和客诉反馈运行几天再评估。逐步放量灰度数据稳定后才逐步扩到30%、100%。如果过程中指标回弹立即回滚到旧版本。Agent项目的迭代尤其要有这个纪律靠感觉不能上线。模型是个概率系统小样本下的优秀表现说明不了真实分布下的可靠性。7. 我在这个过程里最大的转变7.1 从“调通一次”到“稳定跑一周”做Agent开发之前我是在传统后端开发的环境里长大的习惯“写一次、跑一万次都一个结果”的心智。做Agent之后我最大的转变就是接受不确定性模型会犯错、会不走寻常路、会冒出让你哭笑不得的输出这不是Bug这是这个技术形态的属性。所以我不再追求“模型永不犯错”而是追求“犯错之后系统能兜住”。我给自己定了条规矩一个Agent从能演示到敢上线至少要准备两倍于功能开发的评测与护栏时间。这个比例听起来很夸张但实际项目里不过这条线就上线多半会出问题。我现在带项目时也会刻意要求成员先写评测集、先画状态机、先列工具白名单再写系统提示词。顺序反了后面全是坑。7.2 一句让我反复咀嚼的工程口诀最后分享一句我在这个过程中反复咀嚼的口诀“把确定的事情写进代码把不确定的事情交给模型把模型不确定的事情拦在系统外面。”这句口诀大概可以解释我前面聊的所有内容确定的流程、权限、状态转移用代码写死需要判断的意图、参数抽取、方案选择交给模型模型不确定的高风险动作用护栏和人工审批拦在外面。Agent开发做久了你会慢慢发现它其实不只是软件工程更像是在设计一个组织有目标、有分工、有流程、有边界、有复盘。一个稳定的Agent系统本质上是一个把人类协作经验抽象成“协议护栏纠偏机制”的系统。这些经验无法从模型能力本身获取只能靠一遍遍踩坑积攒。希望这篇内容能帮你少踩几个我踩过的坑。