做 AI Agent 工程,最尴尬的时刻不是模型能力不够,而是你发现 Demo 五分钟能跑通,但真要把它变成一个能上线、能维护、敢交到用户手里的系统,横在中间的全是选择题。过去一年我帮团队评审过不少 Agent 项目,几乎无一例外都卡在同一个地方:大家把 Agent 当成一个“会自己想的脚本”,写起来很爽,跑起来也很惊艳,一接真实业务就崩。
后来我把整个思考方式拆成两个框架:先用“七要素”看清 Agent 内部由什么组成,再用“七个决策点”理清工程实现时每一步到底在选什么。这篇就把这两个框架完整讲明白——你不需要先会 LangGraph 或 FastAPI,只需要按这个思路走一遍,就知道一个生产级 AI Agent 是怎么从概念落成代码的。适合正准备把 Agent 搬进业务系统的开发者,也适合想给团队定技术方案但总觉得“网上教程太散”的架构师。
1. 七要素:先把 Agent 拆开,看看一台“有手有脑”的机器怎么组成
很多人描述 Agent 时喜欢说“大模型 + 工具 + 记忆”,这话对,但太粗了。真到了工程层面,我发现一台能稳定干活的 Agent 至少要拆成七个部分,缺一个,后面上线就会拿命补。
1.1 任务边界:Agent 是瑞士军刀还是专用扳手
先回答一个最土但最重要的问题:这个 Agent 到底负责什么,不负责什么。任务边界不是一句需求描述,而是输入输出的严格契约——接受什么格式的消息,产生什么类型的动作,哪些话题必须拒绝,哪些情况必须转人工。
我见过最典型的失败案例,是有人把“智能客服”做成了“啥都能聊的机器人”,结果用户问天气它也答,问股票它也答,最后答错一句,整个产品的可信度就崩了。反过来说,真正能落地的 Agent 往往非常“偏科”:它只做售后工单分类、只做日报生成、只做代码审查建议。边界越窄,行为越可预测,也越好评估。
1.2 模型底座:LLM 是发动机,不是整辆车
第二个要素是模型本身,但要注意一个认知陷阱:LLM 只是发动机,Agent 是整车。发动机决定上限,但方向盘、刹车、仪表盘决定能不能上路。很多人以为“换个更强的大模型,Agent 问题就解决了”,实际不是——你缺的往往是流程控制、状态管理、错误恢复这些“车身部件”。
工程上选模型要看的不是排行榜,而是三个硬指标:推理能力够不够处理带约束的任务、是否支持稳定的工具调用(Function Calling 或 Tool Schema)、以及推理成本和延迟能不能被业务接受。同一个任务,简单分类可能用小模型十几个毫秒就出结果,复杂规划才需要大模型慢慢想,这直接引出后面的“决策二”。
1.3 记忆系统:桌面干净的人,才能干好活
记忆是 Agent 被讨论最多、也最容易做错的要素。我习惯把记忆分成三层:工作记忆(当前任务上下文)、长期记忆(跨会话的历史信息)、程序记忆(Prompt、工具定义、规则配置这些“肌肉记忆”)。
这里有一个反直觉的点:上下文窗口不是记忆。很多新人以为窗口越大越好,于是把几十页历史全塞进去,结果模型注意力被冲散,回答质量反而下降,token 成本还打不住。好的记忆设计是把上下文当桌面——只放当前这步需要的东西,其他资料放文件柜(向量库、Redis、数据库),随用随取,用完归档。
1.4 工具调用:手伸得太长,就容易拿错东西
工具是 Agent 的“手”和“脚”。一个客服 Agent 要能查订单、改地址、发起退款;一个数据分析 Agent 要能查库、跑 Python、画图。但工具不是越多越好——模型每多一个工具可选,选错工具的概率就高一分。
工程上每个工具要定义清楚三件事:名字(动词 + 名词,如query_order)、参数 Schema(严格 JSON,别用自然语言描述参数)、以及描述(说明这个工具是干嘛的、什么时候该用、有没有副作用)。这跟给人写工作手册一个道理,写得越明白,越少出岔子。
1.5 规划机制:先抠 GPS 还是走一步问一步
规划机制决定 Agent 怎么从“用户说了一句话”走到“完成一个多步任务”。目前主流就两派:一派是走一步看一步的 ReAct(推理 + 行动交替循环),适合开放探索型任务,比如“帮我研究一下这个竞品”;另一派是 Plan-and-Execute(先定计划再执行),适合目标清晰、步骤可拆的任务,比如“对所有待处理工单做分类并生成报表”。
生产环境里我见得最多的其实是第三种:固定管线 + 局部决策,也就是预先画好流程图,每个节点内部让模型做选择题,而不是让它自由发挥。原因后面讲决策五的时候细说,总之你先记住:规划机制越自由,系统越不可控,调试成本越高。
1.6 执行状态:能停、能续、能交给人的流程才敢上线
脚本是一次性从第一行跑到最后一行,而 Agent 是一个长时间、多步骤、随时可能出错的流程。执行状态要素想解决的是:任务跑到一半(比如第三步调外部 API 超时了),系统能不能停下来、报个错、重试一次,或者把控制权交给人类审核再继续。
我实践中强烈建议用显式状态图来管理 Agent 流程(LangGraph 就是这么干的),而不是把流程逻辑写在自然语言 Prompt 里让模型“自觉遵守”。代码层面的状态机看得见、摸得着、能测试,Prompt 里的“请按步骤执行”则完全无法保证。StateGraph节点之间怎么跳、什么条件下跳、跳不过去怎么办,都要是显式的、可回放的条件分支。
1.7 观测与评估:没有尺子,就没有优化
最后一个要素最容易被忽略,却是生产环境的生命线。LLM 的输出有概率性,同一个输入换一次调用可能得到不同结果,这意味着:你无法用“这次跑通了”来证明系统是好的。必须有结构化的 Trace 日志、细粒度的评估集和护栏规则,才能回答三个问题:这次回答质量好不好、花多少钱、慢不慢。
做不了观测评估的 Agent 就像不带仪表盘开车——你敢开上路,但出了问题永远不知道是发动机、油门还是路况的责任。具体怎么做,后面“决策七”展开。
2. 从要素到决策:工程实现就是一连串取舍
2.1 Demo 与生产之间,隔着七个选择
把七要素记在脑子里之后,再看“工程实现”这四个字,就会觉得清晰很多:工程实现不是一个动作,而是一连串取舍。Demo 只需要把七要素搓成一条能跑通的路;生产系统则要求在每一个岔路口都选对——因为上线之后,你没法靠“重启一下”来修 Agent。
我把这些岔路口总结成七个决策点,每个决策点都对应前面的一个要素。它们不是按时间顺序逐个完成,而是互相影响、成组出现。比如你选定了多 Agent 架构,模型、工具、状态的设计全部要跟着变;你选了长流程规划,记忆策略就要重新考虑。
2.2 七个要素对应的七个决策点总览
先把整套对应关系放在一张表里,后面逐个展开:
| 七要素 | 对应决策点 | 核心矛盾 |
|---|---|---|
| 任务边界 | 决策一:单 Agent 还是多 Agent | 智能化上限 vs 可控性 |
| 模型底座 | 决策二:一个模型还是大小模型配合 | 效果质量 vs 成本延迟 |
| 记忆系统 | 决策三:上下文放多少、仓库存什么 | 信息完整 vs 噪音成本 |
| 工具调用 | 决策四:开放多少工具、每个怎么定义 | 能力强 vs 容易选错 |
| 规划机制 | 决策五:固定流程还是自由推理 | 确定性 vs 灵活性 |
| 执行状态 | 决策六:状态建模与人工介入点 | 自动化 vs 风险控制 |
| 观测评估 | 决策七:上线标准与持续观测 | 迭代速度 vs 系统稳定 |
这张表是这套框架的核心。你拿着它去套任何 Agent 项目,都能快速定位问题出在哪个环节——是边界没定清楚,还是工具定义太含糊,还是评估手段缺失。下面我把七个决策点分别拆开讲,重点说每一条背后的代价。
3. 前四个决策点:边界、模型、记忆、工具
3.1 决策一:这个 Agent 管多宽,单 Agent 还是多 Agent
第一个决策,也是整个系统的地基:到底做一个什么边界的 Agent,需不需要拆成多个 Agent。
先说结论倾向:能单 Agent 解决的,就不要拆多 Agent。多 Agent 看似各司其职很“高级”,实际上引入了三大麻烦:一是通信成本,Agent 之间用自然语言传递信息,信息一定会失真;二是调试难度,出了问题你分不清是哪个 Agent 的锅;三是资源开销,每个 Agent 都要消费模型调用,成本线性翻倍。
单 Agent 的能力边界卡在哪里?卡在单次任务复杂度。如果任务链路超过七八步,或者需要同时维护多套上下文,单 Agent 的上下文就会很挤。这时候我建议的拆法不是“按功能拆”,而是“按责任拆”——比如一个负责理解分类,一个负责执行操作,中间通过结构化数据传消息,而不是靠文字“你一句我一句”。
实操里我一般先问三个问题:这个任务能不能用一个固定流程描述清楚?如果必须靠模型自由推理才能完成,推理链路有多长?最坏情况下需要同时记住几份相互独立的信息?如果三个答案都偏向简单,闭眼选单 Agent。
3.2 决策二:用什么模型,要不要大模型小模型混着来
第二个决策点最热闹,也最容易踩坑。很多人一上来就选最强模型,理由是“反正效果好”。但在生产环境,“效果好”必须和“成本、延迟、合规”放在一起算账。
我的经验是,一个真实业务里至少有两类任务:一类是固定格式、答案明确的(比如工单分类、关键词抽取、意图识别),这类任务根本不需要大模型“思考”,中等参数模型甚至微调后的小模型就能干,又快又便宜;另一类是开放式、需要推理的(比如写回复、做总结、拆解复杂指令),这必须上强模型。
于是“模型路由”方案就出现了:入口先用一个又快又便宜的分类器判断任务类型,简单任务走小模型,复杂任务才转发给大模型。这种混合架构能省下相当可观的 token 成本,响应速度也好看很多。实现路由的方式也不一定非得上复杂框架,一个 LLM 分类 + if-else 就够。
另外提醒一句数据合规:如果业务数据不能出内网,就别纠结“最强开源模型跑不跑得动”了,直接用可私有化部署的模型(比如 Qwen 系列),或者私有化 API 网关,这比效果排行重要得多。模型这层追求的是“够用还稳”,不是“顶配”。
3.3 决策三:上下文是桌面,存储是仓库,中间是摘要
第三个决策处理记忆系统,核心问题是:哪些信息进上下文窗口,哪些进外部存储,上下文被撑爆了怎么办。
先定一个原则:上下文窗口里只放“当前这一步必须看到的东西”。比如售后 Agent 在处理工单时,工单编号、用户诉求、相关订单状态这三样必须在场;但用户三个月前的购买记录,就不该出现在上下文里,它应该躺在外部存储(数据库或向量库),等需要时再检索出来。
当一段会话变得很长,光靠“裁掉老消息”是不够的,因为关键信息可能就藏在老消息里。我常用的套路是滚动摘要:每处理完一轮就把此前对话压缩成一段结构化摘要,下次调用时把摘要 + 最近几轮完整对话一起放进去。这样既保留了全局信息,又控制住了 token 成本。
再进阶一点就是分层记忆:全局用户画像(长期)、会话摘要(中期)、原始对话(短期)按需组装。工程上建议把这些逻辑封装成独立的记忆管理模块,不要散落在 Prompt 里——Prompt 里的记忆规则,模型完全是“凭感觉遵守”的,模块化代码才是真正可控的。
3.4 决策四:工具是用得越多越好,还是越少越好
第四个决策点直接决定 Agent 的“行动力”。我在 1.4 里说过工具太多会加大选错概率,这里补一组实际数据感觉:模型在 5 个候选工具里的选对率,往往比在 20 个候选工具里的选对率高出不少——开放性候选越多,推理压力越大,越容易在工具描述上产生语义混淆。
所以工具集的设计原则是“够用就好 + 语义清晰”。上线时先只给 Agent 三到五个最核心的工具,跑通了再逐步加。每个工具的 Schema 要写成可以独立理解的小文档:做什么、什么情况下调用、参数怎么填、有没有副作用(比如“此操作不可逆”必须写清楚)。
还有一个很容易被忽视的点:工具返回结果太复杂,一样会把上下文窗口塞爆。你查一个订单接口,可能返回 200 个字段,但 Agent 真正需要的只有 5 个。建议在工具内部做裁剪和格式化,返回给模型的是“精炼后的 JSON”,而不是原始接口大包。这相当于给 Agent 配一个会“先说重点”的助手,而不是把整本说明书砸它脸上。
4. 后三个决策点:规划、状态、上线与评估
4.1 决策五:固定管线还是自由 ReAct
前面说过规划机制三选一,这里重点讲第五个决策点:业务里到底用固定流程还是自由推理。
我的判断标准是:如果任务结果需要可预测、可解释、可追责,选固定管线;如果任务本身就是开放探索型的——例如“帮我查查市场上还有什么竞品在做类似功能”,选 ReAct 式自由规划。排错类任务可以适当让模型在管线内做局部选择,但全局路径必须由流程控制。
为什么这么强调?因为自由 ReAct 的本质是“每走一步都让模型决定下一步做什么”,这在一个有明确 KPI 的业务里是灾难:模型可能突然去调一个无关工具,可能陷入重试死循环,可能在三步之后彻底忘掉用户最初的要求。固定管线恰好把“每一步做什么”写死在状态图里,模型只需要在每个节点里做“小决策”,比如这一步选哪个分支、提取哪些字段。
工程实现上,这套固定管线不要用超大 Prompt 去“感化”模型遵守,要用代码控制。LangGraph 这类状态图框架在这一层价值很大:节点、边、条件、中断、恢复全都在代码里明确定义,模型只负责节点内部的生成任务。这样出问题你可以在图的任一步打断、改参数、重放,而不是对着十几轮对话找“模型哪里想歪了”。
4.2 决策六:状态怎么建模,失败重试和人工审批放哪里
第六个决策点是最容易被新手工程忽略的:Agent 不是一个“一问一答”,而是一个有生命周期的工作流,它的状态必须被建模、被持久化。
先定一个最小状态集:任务 ID、当前节点、输入快照、各节点输出、错误次数、审批状态。这个状态要存在外部存储里(Redis 或 Postgres),而不是存在内存变量里——道理很简单:进程一重启、机器一挂,内存里的状态全没了,客户工单就丢了。
然后是失败重试策略。工具调用一定会偶发超时、返回脏数据、鉴权失败,这些都要在状态图里给出分支:超时就重试,重试两次还不行就转人工;数据校验不通过就回到上一个节点重新抽取。重试要带退避,不要狂轰接口——很多上游系统对突发重试很敏感,会直接限流。
最关键的还是人工审批节点(Human-in-the-loop)。凡是涉及改数据、退款、发消息、下单这类有实际影响的操作,都必须在这个操作前插入一个“待审批”状态,流程挂起,等人工确认后继续。这个设计不只是为了合规,也是给系统兜底——模型再怎么聪明,也不能让它直接对真实世界做不可逆操作。状态图框架里的interrupt能力就是干这个的,用起来比你手写队列靠谱得多。
4.3 决策七:上线前怎么评估,上线后怎么观测
最后一个决策点决定项目能不能“体面地活着”:评估与观测体系怎么搭。
先说评估:别指望“用人眼抽查几条结果”就算评估。上线前至少要准备 50~100 条带标注的测试用例,每条用例写明输入、期望行为、验收口径(比如分类正确、回复包含退款链接、语气合规)。然后跑批,统计指标:任务完成率、准确率、平均工具调用次数、失败率。没有这组数字,你根本不敢跟业务方说“可以上了”。
然后是观测。生产环境每跑一次 Agent,都应该留下一条完整 Trace:用户输入、每一步调了哪个工具、工具返回了什么、模型输出是什么、耗时多少、花了多少 token、命中哪个分支。工具上我推荐 LangSmith 或者 Langfuse 这类可观测平台,能自动把链式调用串起来,出问题以后点开 trace 图一眼看到哪一步歪了。
最后补一个容易被忽略的成本问题:Agent 的 token 消耗是普通 Chat 的几倍甚至十几倍,因为一次任务要反复调用模型。上线前你要给每个任务设 token 预算上限,超预算直接熔断转人工,并且每周做一次成本复盘。评估和观测这层做扎实了,后续优化才有依据——不然每个“灵光一闪”的优化都在蒙着眼睛改系统。
5. 完整推演:一个售后工单 Agent 从零到上线
5.1 需求背景与七要素快照
为了把这七个决策点串起来,我拿一个我们团队实际做过的项目来推演:售后工单自动处理 Agent。业务背景是一家电商公司,每天几百张售后工单,客服人力吃紧,希望让 Agent 自动完成“工单分类 → 查询订单 → 生成回复草稿 → 高风险转人工”这一条链路。
先把七要素快照填一遍。任务边界:只处理售后工单,不闲聊,不做营销推荐;模型底座:公司数据不出内网,用可私有化部署的模型,配合一个小模型做前置分类;记忆系统:会话摘要 + 当前工单信息;工具调用:三个——查订单、查物流、发起退款申请;规划机制:固定管线;执行状态:状态图管理,退款节点前插入人工审批;观测评估:接 Langfuse 做 Trace,准备 80 条标注工单做回归集。
5.2 七个决策点一次落完
第一步定边界(决策一):不拆多 Agent,单 Agent 走完整个工单流程。理由很直接:链路虽然长,但每一步输入输出都很清晰,不需要两个模型互相“商量”,拆成两个 Agent 反而多一层自然语言传递的开销。
第二步定模型(决策二):做一个三层路由——入口用一个小模型做意图识别,判断“这是售后单、是物流催单、还是其他类型”;只有需要生成回复正文时才调用大模型;固定模板场景(比如纯物流催单)用一个规则模板直接回复,连模型都不调。这样算下来,真正走到大模型 step 的请求大概只有四成,成本立刻打下来。
第三步定记忆(决策三):上下文里只放四样东西——工单编号、用户诉求(截取前 500 字)、订单状态摘要、近三轮会话摘要。用户的历史售后记录存向量库,需要时按 top3 召回,不占用主上下文。
第四步定工具(决策四):只开放三个工具:query_order(order_id)、query_logistics(tracking_no)、apply_refund(order_id, reason, amount)。前两个只读,第三个有副作用,工具描述里明确写了“调用后不可撤回,需要人工确认”。返回结果在工具内部就裁剪成模型真正关心的字段。
第五步定规划(决策五):固定管线,状态图四个节点:classify(分类)→lookup(查订单/物流)→draft_reply(生成回复草稿)→human_review(人工审批)。伪代码示意:
from langgraph.graph import StateGraph, END builder = StateGraph(WorkOrderState) builder.add_node("classify", classify_node) builder.add_node("lookup", lookup_node) builder.add_node("draft_reply", draft_reply_node) builder.add_node("human_review", human_review_node) builder.add_edge("classify", "lookup") builder.add_edge("lookup", "draft_reply") builder.add_edge("draft_reply", "human_review") builder.add_edge("human_review", END) graph = builder.compile()第六步定状态(决策六):每个工单任务的状态快照写入 Postgres,lookup节点工具调用超时重试一次,仍失败则写入failed状态转人工;apply_refund之前强制插入human_review节点,流程挂起,等审核人点“同意”才继续。这一步把整个系统的风险控制住了——模型生成错了不用慌,人工在看门。
第七步定上线评估(决策七):先跑 80 条标注工单,重点看两个指标:分类准确率(要求 95% 以上)和草稿可用率(人工审核时需修改比例低于 30%)。上线后每天看 Langfuse 里的 trace 分布:哪个节点耗时最长、哪一个分支命中率最低、平均单量成本是多少。一旦单量成本超预算,就把对应分支切回模板回复。
5.3 上线两周我调整了什么
这套系统上线两周,最出乎我意料的是:分类节点和回复节点都没出大问题,真正拖后腿的是工具返回里的一个小字段——order_status有几种边缘状态(比如“已申请退款待仓库确认”),模型经常把这类状态误判成“退款已完成”,导致回复话术给错。
我们没有急着换大模型,而是做了三件事:第一,在工具返回里把边缘状态单独拆字段并加中文释义,减少歧义;第二,在draft_reply节点前加了一条规则判断,命中边缘状态直接走人工模板;第三,把这类 case 补进回归集,防止后续回归。改完以后草稿可用率从 74% 提到 88%,效果立竿见影。
这个案例想说明的就是:Agent 工程不是搭好架子就完事,它是一个持续用评估驱动迭代的过程——而每次迭代能精准找到问题,靠的正是上线前布好的观测和评估体系。我个人的体会是,大部分 Agent 项目翻车,翻的从来不是模型能力,而是前六个决策没想清楚,第七个决策完全没做。把这套七要素、七决策的框架过一遍,基本能把项目里至少八成的不确定性提前排掉。