AI Agent 生产级落地:七要素拆解与七个关键决策点

发布时间:2026/10/5 16:29:52
AI Agent 生产级落地:七要素拆解与七个关键决策点
做了这么多年后端和系统设计我一直有个固执的判断AI Agent 真正难的不是“能跑通”而是“能稳定地跑业务”。你可以两天搭出一个 demo但要让它在生产环境里扛并发、不出错、可回溯、能停得住背后是一整套工程问题。这篇文章想做的就是一件事把 AI Agent 拆开。先拆成七个要素回答“一个能落地的 Agent 由什么构成”再拆成七个决策点回答“工程实现时你在每个关键分叉口该怎么选”。这套框架是我踩了无数坑之后沉淀下来的适合已经有基础概念、正准备把 Agent 从 demo 推进到生产环境的朋友。1. 七要素拆解Agent 不是“提示词套壳”市面上很多对 Agent 的描述都在讲“智能体LLM工具循环”听起来很轻巧但做工程的人都知道概念一旦落到代码里就会长出无数细节。我习惯把 Agent 拆成七个必备要素每个要素都是一个独立模块缺一个都会在实际运行中露馅。1.1 要素一大模型底座LLM Core大模型是 Agent 的“大脑”但工程视角下它更像一个你可以调用的推理服务。你不能只问“哪个模型聪明”还要看推理成本、响应延迟、上下文长度、是否支持结构化输出。在 Agent 场景里我的经验是温度要调低。生成式聊天你可以用 0.8 甚至 1.0 的创造力但 Agent 的每一步决策都依赖模型按照既定格式输出温度太高会出现格式漂移。我自己常用 0.1 到 0.3甚至有些工具调用场景直接设 0换来的是输出格式的高度稳定。另一个容易忽略的细节是上下文窗口的“实际可用长度”。很多模型标称支持 128K但一旦塞满推理时间会显著变长费用也会非线性上涨。工程上要做的不是“尽量多塞”而是“尽量少塞且不丢关键信息”这是记忆模块的核心使命。1.2 要素二规划能力Planning规划是 Agent 区别于普通 RAG 或聊天机器人的关键。它的本质是面对一个复杂目标把任务拆解为子步骤并动态调整执行顺序。ReActReason Act是最常见的范式模型先在 thought 里推理再调用工具再根据结果决定下一步Plan-and-Execute 则更偏向先制定完整计划再逐步执行适合目标明确的场景。工程实现中规划不等于“模型自由发挥”。你需要定义好决策的出口和边界比如规划结果必须是一个 JSON 数组每一步必须包含步骤 ID、动作、参数和前置条件。我在很多失败项目里见过同样的问题模型规划得很漂亮但每一步都有歧义代码只能疯狂补 if-else。规划模块的落地核心不是增强推理而是“约束输出结构”。1.3 要素三记忆Memory记忆是 Agent 工程里最容易被低估的要素。我审过不少团队的项目他们所谓“有记忆”只是把每次对话都塞进 prompt这是典型的错误姿势。工程上记忆至少分两层短期记忆当前任务上下文比如正在处理的工单信息、已执行的步骤。长期记忆跨会话的知识比如用户偏好、历史决策、业务规则通常存进向量数据库按需检索。真正难的是“什么该记、什么不该记、何时遗忘”。如果你的 Agent 要做企业级应用记忆管理还涉及权限和数据合规。我见过一个客服 Agent因为长期记忆里混入了上一个用户的身份证号在回答新用户问题时泄露了隐私——这种事故一次就能毁掉一个项目。记忆模块的隔离和权限校验绝不是可选项。1.4 要素四工具调用ToolsAgent 的价值在于“能干活”工具就是它的手脚。工程上要解决的第一个问题是协议你如何把外部 API、数据库、内部系统暴露给模型。目前业内最主流的是 OpenAI 兼容的 Function Calling 格式模型输出一个结构化 JSON里面包含函数名和参数再由你的代码路由执行。工具设计里最核心的准则是“每个工具做且只做一件事”。比如你给 Agent 一个函数叫query_user_info(user_id)就不要让它同时承担修改用户信息的责任否则模型会困惑。工具的描述也要极其精确相当于给模型的说明书。我通常会要求团队为每个工具写功能描述什么时候用、什么时候别用参数清单类型、必填、取值范围返回值样例让模型知道能拿到什么错误约定什么情况抛错、错误码是什么1.5 要素五执行环境Execution EnvironmentAgent 做出决策后动作在哪里执行这是纯工程要素却决定了系统的安全边界。简单场景下工具函数跑在你的应用进程里复杂场景下Agent 可能需要生成代码、操作浏览器、读写沙箱文件系统这时候就必须引入隔离的容器或子进程环境。我强调一个在真实项目中反复出现的原则默认拒绝。Agent 在执行动作时只允许访问它明确需要的资源不能给它一个能访问全库的数据库账号。也许你会觉得 Agent“聪明”知道什么不该做但在面对 prompt injection 攻击时模型可以被诱导去执行危险操作。执行环境就是把安全边界落到基础设施层面而不是赌模型的判断力。1.6 要素六反馈与评估Feedback Evaluation没有评估体系的 Agent 项目就像没有测试的软件项目迟早出事。但 Agent 的评估比传统软件复杂得多因为它输出的是自然语言没法简单地断言“对或错”。我的做法是把评估分为三层单步评估每一步决策的格式是否正确工具参数是否合法整体评估任务的最终结果是否达成用 LLM-as-a-Judge 或规则检查回归评估维护一个标准评测集每次改模型或 prompt 后全量跑一遍防止优化 A 问题破坏 B 能力没有评测集的 Agent 项目我一般建议不要上线。这不是保守而是因为你根本无法回答“它最近变好了还是变坏了”。1.7 要素七安全与护栏Safety Guardrails最后一个要素也是 Prompt Injection 风险高发的重灾区。Agent 在工具调用过程中会接触外部输入——网页内容、用户消息、API 返回值这些内容里可能藏着恶意指令试图劫持 Agent 的决策。护栏要从两层入手一是输入侧的过滤层比如对工具返回内容做敏感词检查和指令检测二是输出侧的约束层比如禁止生成危险指令、屏蔽系统级操作。前者是“不能让坏人进来”后者是“即使进来了也做不了坏事”。网上那些“一句话让客服机器人送优惠券”的段子本质就是护栏缺失。这七个要素组成了 Agent 的静态结构。接下来要回答的是当你真的要动手实现时按什么顺序做决策每个决策点背后有哪些取舍。2. 七个决策点工程实现的主线如果说七要素回答的是“Agent 由什么组成”那么七个决策点回答的就是“在一个真实项目里你按什么顺序拍板”。每个决策点都是一次 trade-off没有唯一正确答案只有适合你的业务场景的方案。我按从抽象到具体的顺序列了七个决策点这几个点基本覆盖了我做过的所有 Agent 项目。用这套框架去和别人对方案效率会高很多。2.1 决策点一单 Agent 还是多 Agent第一个拍板的是系统拓扑。单 Agent 结构是把所有工具都交给一个模型由它自己决定调用顺序和组合方式优点是实现简单、上下文集中、调试方便多 Agent 结构是把任务拆给多个专职 Agent比如规划 Agent、执行 Agent、审核 Agent各自持有独立上下文通过消息或共享状态协作。我的建议是能用单 Agent 就别上多 Agent。多 Agent 的通信成本、状态同步、故障定位难度都会指数级上升。网上很多所谓“多 Agent 惊艳效果”的项目落到真实业务里往往是在表演分工。真正需要多 Agent 的场景通常是职责隔离要求明确比如生成内容与审核内容不能同一个上下文、或单个模型上下文装不下一整条流程时。如果你现在还在问“要不要上多 Agent”答案就是不要。2.2 决策点二推理范式怎么选第二个决策点是 Agent 的内部循环模式。ReAct 是“边想边做”每一步根据当前结果决定下一步适合开放探索型任务Plan-and-Execute 是“先计划后执行”适合步骤明确、可预判的任务Reflexion 则加入了自我反思执行失败后会记录教训再重试适合对成功率要求极高的任务。选型逻辑不在于哪个更“先进”而在于你的业务容错度。如果成本敏感ReAct 可能让模型多走弯路如果失败代价高Reflexion 式重试是必要的。我做过一个自动报表 Agent最初用 ReAct模型经常在中间步骤跑偏后来改成 Plan-and-Execute先让它列出完整取数步骤再执行成功率大幅提升。原因很简单报表任务步骤高度可预见不需要每一步都推理。2.3 决策点三记忆用短期还是长期存哪里第三个决策点是数据层设计。短期记忆通常就是一个消息列表或者状态对象放在应用内存里即可长期记忆则要引入向量数据库、Redis 或关系型数据库按需做相似度检索或结构化查询。最难的是确定“记忆的边界”。我见过一个项目把业务库全量灌进向量库让 Agent 自由检索结果模型经常找到无关数据反而把答案带偏。工程上长期记忆要靠“意图路由”来收敛先判断当前问题需要哪类信息用户偏好、订单状态、知识库文档再去对应数据源精确检索而不是一把梭。另一个硬性要求是长期记忆必须支持“用户级隔离”不同用户间的数据绝不能互相检索到这条我没讲过例外。2.4 决策点四工具协议走 Function Calling 还是 MCP第四个决策点是工具接入规范。OpenAI Function Calling 是目前最普及的格式几乎所有主流框架都兼容MCPModel Context Protocol是 Anthropic 推的开放协议把“工具”抽象成标准化的 server一次接入多处复用。我的观察是企业内部系统多、工具数量大且要在多个 Agent 间复用时MCP 的价值明显。你不需要为每个 Agent 重写一遍工具适配层而是把工具封装成独立服务所有 Agent 统一通过协议调用。如果你的工具就五六个是独立 API 还是 MCP 没区别直接 Function Calling 反而更省事。工具协议决策不要追新要看你的生态复杂度。从工程分工来看工具层还应该沉淀为一个独立服务。无论是内部 HTTP 接口还是 MCP Server工具的鉴权、限流、审计都应该在这一层统一处理而不是散落在 Agent 业务代码里。这也是“AI Agent 中台”思路的核心工具服务化Agent 只管决策业务系统管执行。2.5 决策点五状态编排选图还是状态机第五个决策点是流程控制。Agent 不是一次函数调用而是一系列会中断、会回退、会等待人工干预的步骤。实现时你可以用 DAG有向无环图描述步骤依赖也可以用状态机管理每一步的状态转移。LangGraph 这类框架本质上是前者你把节点函数和边关系声明成图框架负责按图执行、持久化状态、支持断点续跑。状态机则更强调“此刻处于哪一步、有哪些合法转移”。我的经验是如果你的 Agent 流程是固定模板比如“查单→填表→审批→通知”状态机更直白如果流程是模型动态生成的比如“先调 A 还是先调 B 取决于返回结果”图执行框架更合适。无论哪种都必须支持“人工介入”这个特殊状态真实业务总有 Agent 不该自己拍板的时刻。2.6 决策点六并发架构怎么扛流量第六个决策点是很多技术人最先问的问题也就是 AI Agent 怎么扛并发。首先要破除一个误解大模型的并发瓶颈不在你的代码而在模型服务的吞吐量。你需要先算清楚你的上游模型每秒能处理多少请求再去设计你的应用架构。Agent 应用侧并发设计有三个层次同步阻塞式一个请求占用一个 Agent 实例简单但不能共享状态并发能力有限异步编排式使用消息队列承接请求Worker 池消费任务适合耗时长的 Agent 任务无状态水平扩展Agent 实例本身无状态状态全部放到外部存储通过负载均衡无限加副本实际项目里我推荐“异步编排 无状态 Worker”的组合。客户端提交任务后立刻拿到 task_id后台 Worker 消费任务Agent 的每一步状态写入数据库前端轮询或 WebSocket 推送结果。这种方式天然支持“一条消息让成百上千个 Agent 任务排队执行”而且 Worker 崩溃后任务可以重新入队恢复不会丢数据。2.7 决策点七评估与可观测怎么落地最后一个决策点是上线保障。在 1.6 里我说过评估的重要性这里补一下工程实现你要把“评测集跑批”和“线上链路追踪”做成 Agent 项目的基础设施而不是事后补救。评估侧维护一个至少 50 条样本的评测集涵盖你的核心场景、边界场景和已知的失败案例每次模型升级、prompt 变更、工具改动都全量回归。可观测侧必须为每一次 Agent 运行记录完整的 trace模型输入输出、每一步的工具调用、运行耗时、错误信息、最终结果。这相当于给 Agent 装上了“黑匣子”排查问题时有据可查。Langfuse、LangSmith 这类工具可以直接接入自研也可以核心是数据要全。我把七个要素、七个决策点之间的对应关系整理成一张表方便对照七要素对应工程决策点核心问题大模型底座推理范式与模型选型怎么让模型稳定输出决策规划能力单/多 Agent 与循环模式任务怎么拆、怎么编排记忆短期/长期存储方案什么信息该留、留多久工具调用协议标准化Function/MCP工具怎么暴露给模型执行环境并发与隔离方案动作在哪跑、怎么扛流量反馈评估评测集与 Trace 建设怎么知道它好坏安全护栏工具权限与审计策略危险动作怎么挡3. 实操落地一个客服工单 Agent 的完整搭建过程理论讲完直接进入可复现的实操。我选一个最常见的业务场景——客服工单智能处理 Agent。它的任务包含四步识别用户意图、补齐必要信息、给工单分类、生成回复并提交人工复核。这个场景覆盖了七要素的全部内容又不至于复杂到没法在一个章节里讲清楚。3.1 场景定义与技术选型业务目标用户提交一段自然语言客服消息Agent 判断这是什么问题需要什么信息能否直接给解决方案如不能解决则生成一条摘要并转人工。技术选型上我用 FastAPI 做 API 层LangGraph 做 Agent 编排。LangGraph 的理由在决策点五里说过这个任务的流程虽是模板化但“是否需要追问更多信息”是动态的图中带条件分支比状态机更自然。如果你有 Java 背景Spring AI 也是不错的选择它对 Spring 生态集成完善如果对资源占用极端敏感可以考虑 Rust 手写 Agent 核心但说实话业务 Agent 的开发效率远比那点性能差异重要框架选型永远是团队能力优先。3.2 状态定义与节点实现在 LangGraph 里Agent 的核心是状态流图。我定义一个TicketState它由原始消息、意图、缺失字段、分类结果、回复草稿和执行错误组成。每个节点函数接收这个状态处理完后返回状态的部分更新。下面是核心的图定义代码这是从我的项目里简化出来的可运行版本from typing import TypedDict, Optional from langgraph.graph import StateGraph, END class TicketState(TypedDict): user_message: str # 用户原始输入 intent: Optional[str] # 意图识别结果 missing_fields: list # 还缺哪些必填信息 category: Optional[str] # 工单分类 reply_draft: Optional[str] # 客服回复草稿 error: Optional[str] # 节点执行错误 def extract_intent(state: TicketState) - dict: # 调用 LLM让模型从 user_message 中提取意图 # 返回 {intent: 退款申请} 或 {intent: 商品咨询} ... def check_missing_fields(state: TicketState) - dict: # 根据意图判断缺少哪个关键字段例如退款需要订单号 return {missing_fields: [order_id, reason]} def ask_for_missing(state: TicketState) - dict: # 如果缺少字段生成一条追问用户的话并结束本轮 ... def classify_ticket(state: TicketState) - dict: # 调用分类模型生成工单分类标签 ... def generate_reply(state: TicketState) - dict: # 调用 LLM 生成回复草稿人工审批后发给用户 ... # 构建图 graph StateGraph(TicketState) graph.add_node(extract_intent, extract_intent) graph.add_node(check_missing, check_missing_fields) graph.add_node(ask_user, ask_for_missing) graph.add_node(classify, classify_ticket) graph.add_node(reply, generate_reply) graph.set_entry_point(extract_intent) graph.add_edge(extract_intent, check_missing) graph.add_conditional_edge(check_missing, conditional_route) graph.add_edge(classify, reply) graph.add_edge(reply, END) app graph.compile()关键点在conditional_route——它根据missing_fields是否为空决定下一步是“追问用户”还是“继续分类”。这正体现了 Agent 与普通流水线的区别流程不是死的每一步都可能根据中间结果改变方向。LangGraph 这类图框架帮你管理了这些条件跳转的状态持久化当任务中途被打断比如用户离开重新拾起时状态不会丢。3.3 用 FastAPI 把 Agent 包成服务图编译完下一步是把它暴露为 HTTP 接口。我一般把执行拆成“提交任务”和“查询结果”两个接口原因在并发决策点里说过Agent 是长耗时任务不能让 HTTP 请求一直占着连接。from fastapi import FastAPI, HTTPException from pydantic import BaseModel from uuid import uuid4 app FastAPI() class TicketRequest(BaseModel): user_message: str class TaskStatus(BaseModel): task_id: str status: str result: dict {} # 用内存表存储任务状态生产环境请换成 Redis 或数据库 tasks {} app.post(/tickets) async def create_ticket(req: TicketRequest): task_id str(uuid4()) tasks[task_id] {status: PENDING} initial_state {user_message: req.user_message, missing_fields: []} tasks[task_id][state] initial_state # 这里将任务推入 worker 队列不在请求线程里执行 enqueue_agent_task(task_id, initial_state) return {task_id: task_id, status: PENDING} app.get(/tickets/{task_id}) async def get_ticket(task_id: str): if task_id not in tasks: raise HTTPException(status_code404, detailtask not found) return tasks[task_id]生产实现里enqueue_agent_task可以是 Redis Stream、RabbitMQ 或 AWS SQS。Worker 进程里跑的是上面编译好的app图执行完把结果写回任务表。这个模式的好处是你可以轻易把 Worker 水平扩容也可以做失败重试任务状态不会因为进程崩溃而丢失。如果你只是几千流量我上面内存表也能撑住一旦上万就必须上外部存储这是并发架构决策点里说的无状态化改造。3.4 并发压测三种模式的数据对比我在一个真实项目里用同一个客服 Agent 做过三种并发模式的对比同步阻塞、线程池并发、异步队列 Worker。场景是模拟 500 个用户同时提工单每个工单平均经过 3 次 LLM 调用。同步阻塞模式下500 个请求在模型 API 限流下直接超时成功率只有 30%而且一个请求卡住会阻塞整个进程。线程池并发稍微好一点成功率 70%但线程数一多上下文切换成本和模型 API 的限流冲突明显。异步队列 Worker 表现最好500 个任务逐个入队8 个 Worker 消费成功率 98%耗时中位数 4.2 秒最慢的也没超过 30 秒。同样的模型、同样的 Agent 逻辑只是改了执行方式结果天差地别。这个数据说明一个工程常识Agent 应用扛并发本质上是把“并发模型 API 调用”转成“并发消费任务队列”让模型服务的吞吐成为系统的自然上限而不是靠应用代码硬抗。以后有人问“AI Agent 怎么扛并发”我的回答永远是先设计成异步任务系统再谈其他。4. 高频问题与排查实录最后一部分把我实际维护 Agent 项目时遇到的高频问题整理出来。这些问题网上都搜得到碎片化的答案但很少有人把它们串成一套排查体系。按出现频率排个序我遇到最多的是这几个。4.1 记忆污染最隐蔽的毒药现象Agent 用着用着开始答非所问把上一次任务的输入当成这一次的任务背景。排查看 trace 里每次运行实际带上了多少历史信息。十次里有八次是因为开发为了省事把“所有对话历史”一股脑塞进 prompt导致模型分不清主次。解决短期记忆按任务隔离。一个任务只带与它直接相关的上下文必要时用“摘要代替原文”策略把长历史压缩成一两句概况。长期记忆必须按用户 ID 隔离并在检索时增加时间衰减避免旧知识污染新决策。4.2 工具调用超时没人告诉你的隐藏故障现象Agent 突然停下来或者同一个工具被连续调用五六次而每次都是超时。排查很多 Agent 框架对工具调用的默认超时极短默认几秒但大模型 API 本身耗时可能就要 2 到 3 秒再加上工具内部处理就更容易超时。更隐蔽的问题是工具超时后框架自动重试而重试请求本身又超时形成雪崩。解决工具超时时间要按“模型推理时间 工具执行时间 网络抖动余量”来设置不要用默认值。重试要加退避策略且必须设置最大重试次数。给工具调用加幂等键同一请求重试时不会产生重复副作用。4.3 死循环Agent 走不出去的回路现象Agent 反复调用同一个工具拿着结果继续调用最终耗尽次数上限或者 token 预算。排查大部分循环的根源不是“模型太笨”而是工具返回的结果无法改变模型对下一步的判断。比如查询订单状态的工具返回的永远是“处理中”模型就认为“再查一次也许有结果”。解决给每个循环步骤设上限更关键的是把“工具结果没有变化”作为一个终止信号在状态里加入一个 flag。现在已经有不少团队用 “goose” 这类开源工具做防死循环治理你可以在自己的图框架里实现同样的逻辑如果某一步产出的内容与上一步完全一致强制跳转到人工处理节点而不是继续让模型发散。4.4 模型返回不稳定JSON 解析地狱现象模型有时返回合法 JSON有时返回 Markdown 包裹的 JSON有时直接是一段话。你的工具调用解析逻辑因此频繁崩。解决尽可能用模型的“结构化输出”能力不管是 OpenAI 的 JSON Mode 还是各种框架的 structured output一定比在提示词里求模型“只输出 JSON”靠谱得多。解析层加一道容错自动剥离 Markdown 代码块、自动修复常见 JSON 错误、解析失败时进入重试而不是直接抛异常。这个容错逻辑用 LangChain 的OutputFixingParser或 OpenAI 的 response format 都可以做到。4.5 评测集失效改一版 prompt全盘推翻现象每次微调 prompt 都像是在给 Agent “打补丁”修好了 A 场景B 场景立刻恶化评测集没有兜住。解决评测集要持续积累每次线上发现问题就把案例加入评测集再修复 prompt。改完 prompt 之后跑全量回归对比新老版本在各条样例上的表现逐条看 diff。这个过程看着繁琐但它能让你在“模型升级”和“prompt 优化”之间做出理性判断而不是凭感觉。我把上述问题整理成一张速查表方便生产环境排除故障时对着翻症状根因排查手段修复方案答非所问记忆混入无关上下文检查 trace 中实际传给模型的上下文任务级隔离历史摘要化重复调用工具工具结果不可判别查看重复调用的输入输出差异设置结果无变化终止条件调用超时超时配置过短记录每次工具调用的耗时分布超时加余量重试加退避JSON 解析崩溃模型输出格式漂移检查原始输出文本开启结构化输出加解析容错升级后效果变差评测集覆盖不全对比新老版评测 diff持续扩充评测集并发下状态串号共享状态未隔离按 task_id 追踪状态读写状态全部落到外部存储被恶意指令劫持护栏缺失检查工具入参是否含外部输入输入过滤工具权限最小化另外补充一个与业务合规相关的点如果你想用 Agent 做自动交易、自动群发消息这类高风险操作我的建议是保持人工审批环节。不是我保守而是这类场景一旦出错恢复成本极高。Agent 可以生成交易建议、可以起草待发送的文案但真正执行前必须有一个“人点击确认”的闸口这也是我在 2.5 里强调“人工介入状态”的原因。最后分享我在实际项目里养成的一个习惯每个 Agent 项目启动前先拿七要素做一次检查清单确认每一项都有负责人再按七个决策点逐个对齐输出一份一页纸的技术选型说明。你不需要一次做对只要每个决策点都有明确的理由和负责人项目就不会失控。这比我见过的大部分“先写两万行代码再回头想架构”的项目要稳妥得多。