
今年陆陆续续做了好几个 AI Agent 项目也帮几家公司评审过他们的“Agent 架构”。最常听到的一句话是“我们已经接了大模型 API也配了 Tools为什么效果还是不稳定”继续问下去基本都是同一个原因——把 Agent 当成了“一个更大的 Prompt”而不是一个需要认真设计的工程系统。做 Agent 工程实现最核心的矛盾在于模型是概率性的而系统需要确定性。你写的代码能精确控制流程但模型下一步会输出什么天然带着不确定性。工程要做的不是消灭这种不确定性而是把它限制在可控节点里让整个状态流变得可观测、可回滚、可测试。所以我一直主张做 Agent 前先把两张图想清楚一张是Agent 由哪些要素组成另一张是每个要素上有哪些决策要做。前者回答“我要造什么东西”后者回答“怎么造才不会返工”。前者我习惯拆成七个要素目标、感知、记忆、规划、工具、执行、反馈后者对应工程实现的七个关键决策点框架选型、模型路由、记忆方案、单 Agent 还是多 Agent、并发治理、可观测性、评估体系。这篇文章就把这两套框架完整拆开顺便给一份基于 FastAPI LangGraph 的可落地骨架。1. 先建立全局观Agent 工程化到底在解什么题1.1 从“写 Prompt”到“写系统”问题域变了很多人分不清“提示工程”和“Agent 工程”的边界。我平时给团队解释的时候会用一句话概括Prompt 决定模型“这一次”输出得好不好Agent 工程决定系统“每一次”都稳定地完成任务。前者是单点优化后者是一条链上的系统设计。单次调用时关心的是温度、指令表达、few-shot 示例到了 Agent 阶段关心的是状态怎么流转、工具怎么调用、上下文怎么维护、出错怎么恢复。你会发现传统后端里那些东西——状态管理、限流、日志、测试、事务——全部回来了而且多了一层模型不确定性的干扰。很多团队踩的第一个坑就是把所有行为约束全部塞进 system prompt。结果 prompt 越来越长模型开始“顾此失彼”token 成本还翻倍。这个问题的本质是目标限定、步骤规划、输出规范这些不同职责应该分散到系统不同节点里去管而不是全压在模型的一段话术上。我把 Agent 拆成七要素就是为了先把职责分开工程上才有地方下手。1.2 七要素框架Agent 的最小完整画布下面这张表是我在项目评审时反复用的建议你把它贴在白板上要素解决的问题工程对应物目标Agent 为什么要做这件事边界在哪里System Prompt、任务参数约束、策略配置感知从外部拿到什么信息才能开始输入 Schema、事件订阅、多源数据汇聚记忆前一步和更早的信息如何保留上下文窗口、Redis/DB 状态、向量库规划任务怎么拆解成可执行的步骤状态图、ReAct 循环、Plan-and-Execute工具模型能力之外的动作怎么做Function Calling、MCP、HTTP 服务执行选定动作后如何可靠地完成执行器、代码沙箱、API 客户端、补偿逻辑反馈结果如何回流并影响下一步观察、校验器、人工介入、评估记录这七个要素首尾相连形成一个闭环感知外部信息 → 结合记忆和目标做规划 → 调用工具执行 → 观察执行结果 → 更新记忆 → 进入下一轮决策。很多框架里所谓的 ReAct、Plan-and-Execute本质都是在这个闭环上做不同粒度的节流。记住两个原则每个要素都必须在系统里有明确的代码归属而不是散落在 prompt 里每个要素都应该能单独测试。如果你的“规划”逻辑藏在一个 3000 字 prompt 里你根本没法对单点做回归测试出了问题也不知道是模型不行还是工具不行。2. 七要素逐一拆解每一环都是工程决策2.1 目标与感知限定边界比扩大能力更重要目标要素很多人以为就是写好 system prompt。实际上生产环境里的“目标”是一套约束集合包括任务边界、行为准则、禁止事项、输出格式、安全限制。举个例子做一个“自动生成小红书图文”的 Agent目标不应该是“帮用户写一篇小红书”而应该拆成内容主题来自用户输入、语气和字数范围固定、必须包含某些平台规范、不允许生成广告法禁用词。这些约束一部分给 prompt一部分写死在代码校验器里。能用代码判断的不要指望模型自我约束。感知要素则容易被忽略。Agent 拿到什么输入决定了它的起点质量。我见过不少项目直接在 prompt 里拼一段 JSON模型就去猜 JSON 里哪个字段是主题、哪个是历史记录。正确的做法是让输入也走 Schema 校验用 Pydantic 或类似工具先反序列化非法字段直接拦截再把结构化对象注入 Agent。实操心得输入上下文的体积要刻意控制。很多 Agent 把数据库全部记录塞进上下文token 爆炸、注意力被稀释效果断崖式下降。业界通用做法是先抽摘要只把最相关的 3~5 条事实喂给模型对时间敏感的数据打上时间戳避免模型把旧状态当新状态输入字段按重要度排序上下文截断时从最不重要的字段开始丢。2.2 规划与记忆Agent 的“大脑皮层”怎么搭规划是七要素里最容易被神话的部分。团队一谈 Agent 就想着“高阶推理”“自我反思”但生产环境里任务规划通常就三种模式固定流程预先定义 DAG每个节点固定做什么模型只负责节点内的生成。适合业务流程明确的场景比如工单处理、审批流转。ReAct 循环模型根据观察结果动态决定下一步动作适合开放性强、路径不确定的任务。Plan-and-Execute先让模型生成完整计划再按计划逐步执行执行中可修订计划适合复杂的多阶段任务。我的建议是默认从固定流程开始什么时候证明需要动态规划再引入 ReAct。因为动态规划意味着更大的不确定性和更高的 token 成本对稳定性是负贡献。记忆要素必须先回答一个“第一性问题”状态到底归谁所有是归会话还是归业务实体如果你做的是一个客服 Agent状态应该跟着工单走而不是跟着会话走。用户换了设备回来业务状态还在历史不会丢。落地时我会把记忆分成三层层级存储介质用途生命周期窗口记忆上下文数组最近几轮对话和动作单次请求业务状态Redis / PostgreSQL任务进度、实体的关键字段任务周期长期知识向量库 / 业务库用户偏好、历史案例、领域知识跨任务这里也顺带解释一下很多人问的“token 是什么意思”。token 是大模型计费和处理的基本单位可以粗略理解成“模型看到的单词碎片”。窗口记忆越短单次调用的 token 越少延迟和成本越低但记忆太短Agent 又记不住前因后果。所以窗口记忆的优化目标永远是用最少的信息量维持必要的上下文连贯性。2.3 工具与执行函数即边界Schema 即契约工具是 Agent 能力的外延。我的观点很明确函数就是边界Schema 就是契约。Agent 能碰什么、不能碰什么由工具白名单决定模型以什么格式调用工具由 JSON Schema 决定。在定义工具时几个容易被忽视的细节工具描述要写清楚“什么时候用这个工具”而不是只写“这个工具做什么”。模型选错工具八成是描述含糊。参数校验一定在进入业务逻辑之前做。模型填的参数经常缺字段、类型错误、数值越界后端要像对待外部请求一样对待模型调用。所有工具都要有超时和错误返回。工具超时不能挂起整个 Agent。工具返回结果要控制长度优先返回结构化摘要而不是原样回传一坨日志。工具返回过长会把上下文塞满导致后续步骤质量下降。执行要素上主流方式有三种Function Calling各模型厂商标准方案、MCPModel Context Protocol通过协议接入远程工具、代码执行沙箱。选择时不要盲目追 MCP——如果你的工具就几个内部 HTTP 接口直接 Function Calling 就够了如果要做开放生态再考虑 MCP。执行层还要考虑幂等性。比如 Agent 调用“扣款”工具如果模型因为超时重试了两次是否会造成重复扣款业界常见的做法是在工具层加幂等键以 session_id step_id 作为唯一标识服务端做去重。2.4 反馈与观察稳定性都藏在这个闭环里反馈环节是大多数 Agent 项目做得最糙的地方。很多人把工具返回结果直接丢回给模型就算完事完全不做质量判断。实际上反馈环节至少要做三件事判断动作是否成功。工具返回非零状态、超时、参数校验失败都属于执行失败要明确标识给模型而不是让它猜。判断是否该结束循环。写死最大轮数max_iterations比如 8 步、15 步超过就强制收尾并降级输出防止死循环烧钱。判断答案是否符合最终约束。设置一个独立的校验器节点把“生成答案”和“校验答案”分开校验失败就走修复分支。我见过不少 Agent 在反馈环节偷懒导致模型反复调用同一个工具拿相同结果既烧 token 又拖时间。加一个简单的规则连续三次执行结果相同就要中断并重新规划。这个规则用代码写不要指望模型自觉。另外反馈环节是人工介入的最好位置。人在环上HITL不是兜底而是一种工程策略。高风险操作支付、删除、对外发布在反馈节点加上人工确认比让模型自己拍板安全得多。3. 七个决策点从选型到落地每一步都有取舍3.1 决策一框架选型——LangGraph、自研状态机还是平台框架选型是第一道分水岭。现在市面上大致有三类路线LangGraph把 Agent 编排显式建模成状态图节点、边、状态转移都代码化支持 checkpoint 持久化和并发控制。适合需要复杂编排、生产级可控性的团队。自研状态机业务逻辑非常简单、路径固定用 if-else 或状态机库自己写比引入框架更省事。缺点是要自己实现重试、持久化、追踪。平台型产品比如扣子、Dify 这类低代码平台适合快速验证和非技术团队。优点是上手快缺点是黑盒出现问题排障困难。另外Java 技术栈团队可以关注 Spring AI 的 Agent 支持对资源占用敏感或有高性能诉求的团队也可以看到 Rust 生态里开始出现一些 Agent 运行时项目。选型的核心不是“哪个火”而是“谁来维护、出问题能不能排”。我的建议很简单超过两个分支流程的 Agent 直接用 LangGraph不要自己造轮子如果只有一条直线流程自己写状态机反而更清爽。这里有一个很现实的理由LangGraph 的 checkpoint 机制帮你解决了“状态持久化”这个难题自研要在这个问题上投入大量精力还不一定比它成熟。3.2 决策二模型选型与路由“一个 Agent 用一个大模型”是典型的大炮打蚊子。真实场景里不同任务的难度差异巨大分类、提取、摘要这些环节用小模型就够只有最终开放式的推理步骤才需要顶级大模型。我习惯在 Agent 内部做一个模型路由层任务类型模型档位使用建议意图分类 / 实体提取轻量级模型温度调低速度优先工具调用参数生成中档模型开启严格 Function Calling 模式复杂推理 / 最终答案旗舰模型允许更多思考空间但别全流程都用它成本上把轻量任务的调用转去小模型能直接砍掉 50%~70% 的 token 费用。我的实际经验是一个客服 Agent有 80% 的轮次是简单问答只有 20% 需要复杂推理路由策略下总成本大概是原来的一半出头。除了模型档位还有一个容易忽略的参数是 temperature。写代码片段、参数提取的任务temperature 设成 0 或接近 0内容创作类任务可以放权到 0.7 以上。不少团队全流程一个参数结果该稳定的不稳定该有创造力的又像机器人。3.3 决策三记忆如何分层存储记忆方案的选择直接影响并发下的正确性和长期使用的体验。我的建议是分三步走第一步先确定“业务必要状态”有哪些用 Redis 或 PostgreSQL 存。比如客服场景的工单号、用户 ID、当前步骤、已收集字段。这部分是强一致、必须不丢的。第二步把历史对话做摘要压缩。一个 Session 超过 N 轮之后把之前的对话交给模型做 summarize用摘要替换原始记录。摘要可以分层每次滚动摘要只保留前一次的摘要加本轮的 key information。第三步才考虑向量库。向量库是给“跨会话召回”用的不是给“当前会话记忆”用的。很多项目一上来就上向量库结果发现查询模式模糊、召回质量差还增加了系统复杂度。你需要先问清楚到底要召回什么按什么相似度度量TopK 取多少记忆还有一个独家的细节写入记忆的数据也必须是 Schema 约束过的。如果模型输出的摘要乱写或者工具返回值未经清洗就入库长期记忆会越积越脏。建议在写入前加一层清洗和去重同一实体的字段值以时间戳最新为准。3.4 决策四单 Agent 还是多 Agent热词里“主流架构”往往指向多 Agent因为听起来很灵活。但我的实际经验是多 Agent 的复杂度是指数级上升的能单 Agent 解决就尽量单 Agent。多 Agent 的主要收益是职责分离与并行度主要代价是通信开销、错误传播和观测复杂度。三个 Agent 互相调一会儿一次失败会引发连锁反应排障时你都不知道该看谁的日志。什么时候值得上多 Agent任务天然被分成多个专业领域每个领域的工具集差异巨大。比如一个负责售前、一个负责售后。单个 Agent 的上下文窗口已经不够用把不同环节拆到不同 Agent 里隔离上下文。需要并行处理多个独立子任务以降低延迟。如果你决定上多 Agent优先选最简单的协作模式Supervisor 模式。一个调度 Agent 负责分配任务多个子任务 Agent 各自执行并汇报比让 Agent 之间互相讨论要可靠得多。架构上对应 LangGraph 里的 Send API 或手工实现的 worker 队列。3.5 决策五并发能力与流量治理“AI Agent 怎么扛并发”是最近常被问到的问题也是很多 Agent 从原型走向生产的必经关卡。和普通 HTTP 服务不同Agent 的一次请求可能内部要多次调用大模型 API耗时动辄几十秒而且每次调用的上下文都不同很难简单缓存。针对这个问题我总结了四个关键手段第一状态必须外部化。Agent 运行中的状态不能放在进程内存变量里否则多实例部署时同一个用户请求分配到不同实例就串了。用 Redis 或数据库保存 stateLangGraph 里可以用 checkpointer 实现。第二控制模型 API 的并发配额。大模型厂商一般会给出 RPM每分钟请求数和 TPM每分钟 token 数限制。在服务里要做两层限流一层是对用户请求的并发控制防止单个用户刷爆配额一层是对上游模型的