这两年 AI Agent 的工程实现出现了一个很明显的分化:一边是朋友圈里惊艳的 Demo,一边是生产环境里跑不动的系统。我见过不少团队卡在同一个位置——提示词写了十几版,工具也接了三四个,但 Agent 的表现始终不稳定,要么绕圈,要么瞎答,要么上下文一长就“失忆”。坦白说,问题不在某个环节,而在于大多数人在动手前缺少一张完整的地图。
这篇文章想把我最近复盘下来的“七要素”和“七个决策点”完整拆开来讲。七要素是 Agent 系统里必须有、也必然会涉及的组件;七个决策点是工程落地时你必须拍板、无法回避的选择。适合正在做 Agent 落地的开发者、架构师参考,也适合想从零搭一个能扛住真实流量的 Agent 的团队。全文不绕弯,直接讲干货。
1. 七要素:一个能用的 Agent,最少需要哪些组件
很多初学 Agent 的人以为“模型 + 提示词”就是全部,这个理解在玩玩具时够用,一旦进入真实业务,漏洞会立刻暴露。我习惯把一个可工程化的 Agent 拆成七块:模型、提示词、工具、记忆、规划、行动、知识。下面逐块讲清楚它们各自承担什么职责,以及工程上最常见的坑。
1.1 模型:Agent 的“大脑”,但不是万能的
模型是整个 Agent 的推理中枢,所有决策、理解、生成都从这里出发。选模型时最常踩的坑是“什么强上什么”——GPT-4 级别的模型在复杂推理上确实优秀,但成本和处理速度往往是瓶颈;而轻量模型在简单任务上反而更快更省。
工程上要看三个硬指标:上下文窗口、工具调用(Function Calling)的稳定性、推理成本与时延。工具调用的稳定性尤其重要,模型能不能准确地把“用户说的一句话”映射为“结构化的工具入参”,直接决定了 Agent 的可靠程度。我实测下来,不同模型在同样一份工具定义下,参数提取的准确率能差出 20 个百分点以上,这个差距在真实业务里就是“能用”和“不可用”的区别。
另外,别忽视模型的服务化形态。线上 Agent 通常不会直接调用模型厂商的对话接口完事,而是会加一层路由:简单问题走轻量模型,复杂问题升级到强模型,这种“模型分级”策略能省下可观的成本,后面在决策点里我会细说。
1.2 提示词:不是“写作文”,而是“定契约”
提示词在 Agent 里承担的角色比在普通聊天里重得多。普通聊天里提示词只是引导语气和风格,Agent 里提示词要约束三件事:任务边界、输出格式、工具使用规则。换句话说,它是你和模型之间的接口契约。
我写 Agent 提示词的经验是:不要长篇大论堆形容词,而是用结构化片段。比如一个客服 Agent 的系统提示词,我会明确写:你是电商售后助手;你可以调用查询订单、查询物流、提交退款三个工具;当用户询问价格时,必须调用查询订单工具后回答,禁止凭记忆猜价;当信息不足时,输出特定标识并主动追问。这些约束要像代码注释一样精确,而不是“请你尽量友好地帮助用户”。
另外一个容易被忽略的点是提示词里的“变量区域”。真实场景里,用户身份、历史订单、当前页面信息都要动态拼进提示词,这个拼接过程要放在服务端做结构化管理,而不是让模型自己“脑补”。把提示词模板化、版本化,是 Agent 工程化的重要一步。
1.3 工具:Agent 的“手脚”,决定能力边界
没有工具的 Agent 只是一个高级聊天机器人。工具的类型很多:查数据库、调 HTTP API、执行代码、操作浏览器、发消息,本质上都是把模型的能力延伸到外部世界。工具定义的关键是“模型能看懂”的接口描述。
这里有个工程细节值得展开。每个工具在给模型看时,需要三部分信息:工具名称、功能描述、入参 Schema。模型会根据描述决定“该调哪个工具”,根据 Schema 生成“调用参数”。所以描述要写场景化的触发条件,而不是简单的“获取天气”。举个例子,与其写“获取天气”,不如写“根据城市和日期获取天气,当用户提到今天/明天/周末天气时使用”。Schema 里的每个字段也要写清楚含义和枚举值,否则模型会把“上海市浦东新区”整体塞进 city 参数里,这类问题我在线上见过太多次。
工具返回值同样需要规范化。模型读到的是返回结果,如果返回一段又臭又长的 JSON,模型会“看不过来”。工程上可以在工具内部先做摘要加工,再返回给模型,比如查询订单接口先过滤掉无关字段、只保留状态和时间节点,模型处理起来会顺畅很多。
1.4 记忆:短期窗口和长期知识,得分开管
记忆是 Agent 区别于单次聊天的关键。工程上要把记忆拆成两层:会话级短期记忆和用户级长期记忆。短期记忆通常由模型的上下文窗口承担,记录当前这轮对话中的问答和工具返回结果;长期记忆则要落库,常见做法是把用户的关键偏好、历史决策摘要存进数据库或向量库,下次对话时按需检索出来塞回提示词。
我见过不少项目把短期记忆和长期记忆混在一起,全部灌进上下文,结果 token 消耗爆炸、模型注意力分散。正确的做法是给记忆分生命周期:临时的状态放会话,稳定的事实放长期库。这里要特别提醒:长期记忆写入时一定要做“清洗”,不要原文存对话,而要提炼成精简摘要。比如用户说过“我住在杭州,通勤一般坐地铁”,存下来的应该是“常住杭州,通勤交通方式为地铁”,而不是一整句聊天记录。摘要后的记忆检索命中率远高于原始对话文本。
1.5 规划:从“走一步看一步”到“分步拆解”
规划能力决定了 Agent 面对复杂任务时的表现。最简单的方式是让模型自由发挥,一步步决定下一步动作,这叫 ReAct 模式,适合任务链条短、工具数量少的场景。但复杂任务需要更明确的拆解:先让模型分析用户意图,生成一个多步计划,再逐步执行。这个思路叫 Plan-and-Execute,相当于先写执行大纲,再逐条落地。
工程上要注意规划结果的“可校验性”。模型的计划不一定合理,所以要在每一步执行时做校验:工具是否存在、参数是否齐全、预期结果是否达成。如果某一步失败,要有重新规划的逻辑,而不是卡死。另一个实用技巧是给规划加“步数上限”和“超时控制”,避免 Agent 在复杂意图上无限循环,这是我后面会再次强调的止损机制。
1.6 行动:执行工具调用,并处理反馈回路
行动层是 Agent 真正接触外部系统的地方,也是最容易出事故的地方。调用工具有几个工程要点:超时控制、错误捕获、结果校验、幂等控制。尤其是幂等,工具如果涉及提交操作(发消息、创建工单、扣减库存),一旦 Agent 因为超时重试而重复执行,后果会很严重。必须在工具层加上请求唯一 ID 一类的防重设计。
行动层还要考虑“反馈回路”。模型调用工具后,拿到的不一定是一次成功的返回。工具可能超时、可能返回空、可能报错,这些反馈要结构化地传回给模型,让模型有机会修正参数再次尝试,或者告知用户当前无法完成。我在生产环境里会保留一个“最近一轮动作记录”,包括模型决策、工具调用、返回结果,方便排查和重放。
1.7 知识:Agent 的“外挂资料库”
知识和记忆不同,记忆是用户相关的,知识是业务相关的。Agent 要回答专业问题,往往需要接入企业内部的文档、商品库、政策条款,这就形成了 RAG(检索增强生成)管线。RAG 的工程链路包括:文档解析、文本切片、向量化、向量检索、结果重排、上下文压缩。
这里我想强调切片和重排这两个最容易被看轻的环节。切片大小和重叠策略直接影响检索命中率:切太碎会丢失上下文,切太大又会让无关内容污染向量。重排则是召回后的“二次筛选”,因为向量检索的第一轮结果往往带噪声,用一个轻量重排模型把最相关的片段提到最前面,回答质量会有直观提升。RAG 做到最后,本质成一个数据工程问题,而不是机器学习问题。
2. 七个关键决策点:动手前必须拍板的取舍
组件明确了,接下来是决策。同一个 Agent 需求,不同团队做出来天差地别,往往不是能力差异,而是在七个决策点上选了不同的路。每一个决策都涉及成本、效果、维护性的权衡,没有绝对正确,只有适合场景。
2.1 模型选型:闭源旗舰还是开源微调?
第一个决策点也是最重要的——用哪个模型。闭源旗舰的优势是开箱即用、推理能力强、工具调用稳定,但成本高、数据出域存在合规顾虑、响应延迟受限于厂商。开源模型则相反:可以私有化部署、成本可控、延迟可优化,但需要自己做推理优化和指令微调,技术投入更大。
我的建议是分场景选择:对准确率要求极高、业务链路复杂的场景,直接用强闭源模型兜底;对成本敏感、数据敏感、需要高并发的场景,用开源模型 + 微调。还有一种常见搭配是把两者混用:复杂推理走闭源,简单意图走开源,在服务层做路由,这种混合策略在实际项目中性价比非常可观。工程实现时,尽量把模型调用封装在统一接口后面,做到上层业务不感知底层模型型号,方便随时切换。
2.2 实现语言:Python 稳扎稳打,Rust 追求极致性能
Agent 的实现语言选型,直接影响团队开发效率和系统资源占用。Python 是当前 Agent 生态最丰富的语言,LangChain、LlamaIndex 等框架、大量模型 SDK 都是 Python 优先,团队招人、调试、迭代都最方便,绝大多数项目选 Python 不会错。
但如果你做的是高并发、低资源消耗的 Agent 服务,Python 的 GIL 和解释器开销会成为瓶颈。最近基于 Rust 的 AI Agent 热度很高,Rust 的优势在于内存安全、并发性能好、二进制体积小、启动速度快,适合部署在边缘节点或追求极致成本的场景。代价是开发效率低、生态相对薄弱。我的判断是:中小团队和快速验证阶段无脑选 Python;当单实例并发上到几百 QPS 且单位资源成本敏感时,再考虑用 Rust 重写核心路径。另外,Rust 和 Python 也不是二选一,很多项目用 Python 写业务编排、用 Rust 写高性能工具执行层,各取所长。
2.3 提示词策略:简洁指令还是详细上下文?
提示词要不要写很长?这要分情况。模型能力越强,越不需要冗长的“小作文式提示词”,强模型对简洁指令的理解能力已经很好;模型能力偏弱时,详细上下文和示例反而能明显拉高表现。这里的工程原则是:提示词的内容要跟着模型走,而不是跟着“标准模板”走。
另一个决策点是:把规则写在系统提示词里,还是放在工具定义里,还是放在外部 RAG 里。我的经验是能用工具定义表达的限制就不要写进提示词,能用结构化数据表达的规则就不要用自然语言。比如“查询订单前必须先获取用户ID”,这个约束应该体现在工具入参的必填校验里,而不是提示模型“请你先获取用户ID再查询”。把规则下推到数据和代码层,比靠模型自觉可靠得多。提示词里只保留模型真正需要“思考”的部分,这样既省 token 又降低出错率。
2.4 工具接入协议:自研 API 封装还是接入 MCP?
工具接入方式是一个容易被忽视但影响深远的决策点。传统做法是为每个工具手写 API 封装,然后以 Function Calling 的格式暴露给模型;这种方式的优点是可控性强、依赖少,缺点是每个工具都要自己处理鉴权、重试、错误映射。
而 MCP 是这两年工具接入协议里很受关注的方向。它的核心是把“工具描述、参数 Schema、调用传输”标准化,让 Agent 和工具之间通过一套统一协议对接。好处是生态复用:一旦你的工具实现了 MCP Server,任何支持 MCP 的 Agent 都能直接调用,不用为每个模型厂商重写一遍工具接入。适合工具数量多、需要跨 Agent 复用的场景。但 MCP 也有代价:多一层协议转换、调试链路变长、部分能力受限于协议表达。我的建议是工具少、业务强耦合时直接自研封装更简单;工具多、复用面广时再引入 MCP 做标准化。不必盲目追新。
2.5 记忆层设计:要不要上向量库,存什么,存多久?
记忆层的设计决策比很多人想象的要复杂。第一层问题是:要不要引入向量数据库。如果记忆只是简单的键值存储(用户 ID 到偏好摘要),用 Redis 就够了,没必要上向量库;只有当记忆需要在语义层面被检索(比如从几十万条历史记录里找到“和当前问题最相关的三条”)时,向量库才有价值。
第二层问题是存什么。常见策略是分层存储:原始交互留日志、清洗后的偏好存 KV、对话片段和文档产出存向量。每层的保留周期也不一样,原始日志可能只留 30 天,用户画像级别的记忆则长期保留。这里要特别重视“遗忘机制”,不是所有历史都值得永远记住,定期清理、合并、过期的记忆,既是成本控制,也是对用户隐私的尊重。
2.6 编排模式:单 Agent 死磕还是多 Agent 协作?
一个 Agent 干所有事,还是拆分多个各司其职,是架构层面最重要的决定。单人 Agent 的优势是上下文完整、流程简单、调试直观,适合工具不超过十几个、任务链条中等的场景。一旦工具数量膨胀、职责边界模糊,单个 Agent 会因为“决策空间过大”而频繁选错工具,这时就要考虑拆分。
多 Agent 的常见模式是“编排器 + 工作器”:一个主管 Agent 负责理解意图、拆任务、调度,多个专业 Agent 分别处理客服、搜索、数据查询等子任务。拆分的好处是每个子 Agent 的提示词、工具集、上下文都可以做得非常专注,整体准确率更高;代价是设计复杂度飙升、通信开销增加、调试更困难。我的实践观点是:先单 Agent 跑通,遇到明确的错误分类和上下文互相干扰问题时,再把 Agent 拆开,而不是一开始就上一套复杂编排。
2.7 部署与运维:进程常驻、容器化还是 Serverless?
最后一个决策点是部署形态。Agent 服务和普通后端服务一个显著区别是它可能会“长时间思考”,一条复杂请求可能持续几秒甚至几十秒,这给部署带来了特殊挑战。最简单的方案是常驻进程配合队列,把几十个并发请求排队处理,适合内部工具型 Agent 和中小规模流量。
容器化是常见的中坚方案,重点要做好流式响应、水平扩缩容和会话状态外置(不能把会话内存放在容器里)。Serverless 则适合明显峰谷流量、低频但偶发抖动的场景,代码冷启动和响应时间限制需要实测。另外运维上必须有可观测性和成本监控两件套:可观测性至少要能跟踪“每轮对话里模型收到了什么、工具返回了什么、为什么选了某一个工具”;成本监控要细化到“每个用户平均每次请求消耗多少 token、多少钱”。没有这两样,Agent 上线后几乎等于盲飞。
3. 端到端实例:一个“工单智能助手”的工程闭环
七要素和七个决策点讲完后,我用一个具体的工程实例把它们串起来。假设我们要做一个“工单智能助手”:用户在售后系统提交问题,助手自动理解诉求、查询订单、检索知识库,然后回复处理方案,必要时自动创建升级工单。这个例子麻雀虽小,五脏俱全。
3.1 需求拆解与方案选型
我先按七要素做拆解。模型:采用“双路策略”,简单问题走轻量模型,复杂纠纷走强模型。提示词:定义成“工单处理专员”,输出固定格式的结构化结论。工具:需要查询订单、查询物流、检索售后政策、创建升级工单四个工具。记忆:短期记忆存当前工单上下文,长期记忆存用户历史售后偏好(比如“用户此前对退换货周期有过不满”)。规划:简单工单用 ReAct 直答,复杂工单先拆任务再执行。行动:所有工具都做超时重试和幂等控制。知识:接入售后政策库和常见问题库,走 RAG。
这个方案在决策上是刻意“折中”的:不崇拜新框架、不上多 Agent、不用 Rust 重写,因为第一版的目标是快速验证业务效果。后续如果工单类型持续分化,再考虑拆分专业 Agent。
3.2 工具设计与模型调用细节
工具设计我采用了自研封装优先。以“查询订单”为例,入参是 order_id 和 user_id,模型容易犯的错误是只传一个参数,所以在 Schema 里我把 user_id 描述为“当前对话用户ID,必须先从不变量中注入,不能由模型推断”。这样就把规则从提示词下推到了工具层,明显降低了参数缺失的概率。
工具返回的处理同样关键。查询订单接口返回的原始 JSON 有一百多个字段,我让工具内部先做字段筛选,只保留订单状态、商品名、价格、售后状态、最近物流节点,并且把时间格式统一为“x 天前”这样的相对时间。测试下来,这样处理后模型对状态的解读准确率明显提升,也不会在回复里引用无关字段。
调用模型时,我设置了温度趋近于 0 以稳定输出,同时把工具调用结果和系统提示词结构化拼装在同一轮对话里。所有模型的输入输出都有日志,每条日志里记录了 token 数、响应耗时、工具调用序列,方便后续成本核算和问题回溯。
3.3 提示词编排与多轮稳定策略
提示词我分成三段。第一段是角色与目标,第二段是工作流规则(先查单、再查知识库、最后答复),第三段是输出格式约束(必须按指定 JSON 结构输出处理结论)。三段各司其职,角色段让模型代入,工作流段保证逻辑顺序,格式段保证下游解析稳定。
多轮稳定的策略有几个小心得:一是每次工具返回后,我会在返回内容前加一行“工具执行结果(供参考,不要向用户直接复述冗余字段)”,减少模型把原始 JSON 念给用户听的情况;二是当用户输入与当前工单无关时,提示词里明确“只处理与当前工单相关的售后问题,无关请求直接回复无法处理”,避免 Agent 被带偏;三是对每轮回答都做输出格式校验,不满足 JSON Schema 就自动重试一次。这套组合下来,工单助手的格式错误率降到了一个很低的水平。
3.4 记忆与知识管线的轻量实现
长期记忆第一版没有引入向量库,而是用了 MySQL 存储用户偏好摘要,原因是工单场景下偏好维度有限(用户、商品类目、历史结论),用结构化字段存储和查询比向量检索更直接。摘要的生成会在每轮工单结束后异步执行,把“用户对价格敏感”“用户倾向于换货而不是退货”这样的结论写入用户表。
知识库的 RAG 管线则简单一点:先把政策文档按章节切片,每段 300 到 500 字并保留 50 字重叠,然后用 embedding 模型向量化后存进向量数据库;检索时先根据工单类型过滤类目,再在类目内做向量召回,最后取 Top 3 作为上下文。加过滤这一步是为了避免检索到其他部门的无关政策,属于很便宜但效果显著的优化。
3.5 上线部署与观测体系
部署我选择了容器化方案,一个服务实例承载流式响应,前端通过 SSE 逐字展示 Agent 的思考过程,这是一个很有效的用户体验手段。会话状态外置到 Redis,实例可以随时水平扩展。由于工单助手是内部系统,并发压力不大,单实例加容器自愈已经足够,没有引入 Serverless。
观测体系是上线前必须做好的。除了常规的日志和指标,我专门加了一个“决策轨迹表”:每一轮记录用户输入、模型使用的工具、工具返回摘要、模型最终输出。这个表在后排查问题时几乎是救命稻草。成本监控上,我用日志聚合统计每个用户平均 token 消耗和单日总成本,设置了一个周预算,预算快用完时触发告警,避免模型调用失控导致账单异常。
4. 常见问题与排查技巧实录
最后分享一些这个项目里真实踩过的坑和排查方法。这些问题很多是 Agent 项目特有的,不看决策轨迹很难一眼定位。
4.1 Agent 在同一个问题上反复绕圈
症状是模型反复调用同一个工具,或者多次提出相同计划,始终得不出结论。最常见的原因是规划缺少步数上限,模型没有“适时放弃”的机制。另一个原因是工具返回的信息不足以支撑决策,模型只能一遍遍尝试。排查时先看决策轨迹,确认是不是某次工具返回内容为空或不完整,如果是,优先优化工具返回的摘要质量;同时一定要在编排层加“最大轮次限制”(比如 8 轮),超过后直接转人工兜底,宁可承认失败也不能无限循环。
4.2 模型总是传错工具参数
这是高频问题。比如有“查询订单”和“查询物流”两个工具,模型在用后者时可能把订单号当物流单号传进来。我的经验是三个层面逐级排查:先看工具描述是否说清了“什么时候用”和“什么时候不用”;再看 Schema 字段描述是否包含示例值;最后检查是否因为工具数量太多导致混淆——如果十几个工具让模型频繁选错,就该考虑拆分 Agent 或者给工具按业务域分组了。
4.3 上下文越来越长,token 消耗失控
一个复杂工单如果来回二十轮,每轮都带着完整历史,token 消耗会膨胀得很快。解决思路是“分段压缩”:早期轮次快速压缩成若干摘要节点,只保留最近的 4 到 6 轮完整对话。同时,工具返回内容要做到“返回即摘要”,把大 JSON 字段过滤掉再进上下文。成本的监控也要做到日均趋势可视,发现某个场景消耗异常升高时,大概率是某类工单触发的工具链过长,可以针对性地压缩该链路的上下文。
4.4 模型不遵守输出格式
有时明明在提示词里写了“必须输出 JSON”,模型还是会夹带解释文字。这个问题在弱模型上尤其明显。除了提示词里多次强调,我更推荐在服务端做两层保险:第一层是在解析失败时自动补一次“仅输出 JSON”的重试提示,第二层是解析仍失败时用规则从文本里提取 JSON 片段。工程上永远不要假设模型百分百听话,每次输出都按“可能不听话”来做兜底,才能保证下游流程稳定。
4.5 流式响应体验差、首字延迟高
Agent 在调用工具时,用户会看到长时间没有输出。这个问题的根源是“思考”和“打字”的节奏不好平衡。我的优化是让 Agent 先输出一小段“正在处理什么”的中间状态,再开始执行工具调用,这样用户端能感受到系统在工作。首字延迟高除了模型原因之外,还要检查是否每一轮都把全量工具 Schema 发给模型,工具定义很长时会拖慢生成速度,可以考虑按意图预选一部分工具子集再发。
4.6 线上故障排查无从下手
Agent 系统的故障排查比普通接口难得多,因为“理解、规划、调用、生成”每一步都可能出错。我的建议是上线前一定要把“决策轨迹表”做出来,这个表默认记录每个请求的完整链路。排查时按照“意图理解是否正确、工具选择是否正确、工具参数是否正确、工具返回是否可用、生成结果是否合理”五步定位,基本可以迅速锁定问题环节。如果没有轨迹表,出了问题只能靠复现碰运气,那会非常痛苦。
5. 写在最后:我的一点个人经验
做了不少 Agent 项目之后,我最大的体会是:Agent 工程的核心不在于模型多聪明,而在于你把可控和不可控的边界分得多清楚。模型天生有随机性,工程要做的是把这种随机性关进笼子里——用结构化提示词约束输出,用工具 Schema 约束参数,用编排规则约束流程,用轨迹日志约束可观测性。你每多一层约束,Agent 的稳定性就多一分保障。
最后分享一个小习惯:我每天会花十分钟浏览一遍当天的决策轨迹日志,不只看错误,也看那些“虽然成功但过程很曲折”的案例。这些案例往往提示了工具设计或提示词里的隐性问题,提前修掉,就能避免它们在下一次流量高峰时变成故障。Agent 不是写完就能躺平的系统,它更像一个需要持续做“行为矫正”的协作对象,你越懂它,它越好用。希望这篇文章能帮你少踩几个坑,把时间和精力花在真正有价值的地方。