
这几年凡是做 Agent 的项目最容易翻车的其实不是模型能力而是流程设计。你说它是个“AI 应用”可真正写起来更像是在搭一条生产流水线输入什么、走几步、每一步谁负责、结果谁校验、失败了怎么重来全都要提前定好。这篇文章想把我沉淀的一套 AI Agent 开发流程整理出来从边界判断、核心循环、记忆与工具设计再到评测和上线迭代按真实落地顺序讲一遍。适合那些已经让单轮对话 Demo 跑通、但一接真实业务就卡壳的开发者也适合准备把 Agent 交给客户或团队实际使用的技术负责人。文章里有不少配置和伪代码可以直接改着用。1. 先定边界什么任务才值得用 Agent 来做我做过一段时间 Agent 后发现很多团队的问题不是“不会做”而是“什么都想做”。把一个本可以用规则脚本五分钟跑完的场景硬生生套上动态规划最后模型反复横跳成本翻倍效果反而不如固定流程。所以 AI Agent 开发流程的第一步不是选框架不是写提示词而是把边界画清楚。你要先回答一个问题这个任务的目标是不是可枚举的中间有没有外部反馈失败之后能不能安全重试1.1 按任务形态决定固定流水线、动态规划、长期自治同样是叫 Agent实际工程形态差异很大。我一般会把任务分成三类固定流水线型、动态规划型、长期自治型。形态典型场景模型承担的工作主要工程点固定流水线工单分类、邮件回复、表单初审填参数、做单项判断参数校验、异常重试动态规划行业调研、数据分析、排期调度拆解任务、选择工具执行图、状态追踪长期自治持续监控、库存优化、自动巡检目标分解、多轮决策记忆、审计、人工兜底固定流水线适合步骤明确、顺序基本不变的任务。模型的作用其实只是“填空”把用户输入里的关键信息提取出来塞进预设的模板。比如电商售后工单的自动分类判断“退款”“换货”“物流咨询”三个意图再调用对应子流程就够了。这种场景没有必要让模型自己决定下一步干什么反倒是代码写死的状态机更可靠。动态规划适合那种连开发者也说不清完整路径的任务。模型需要根据当前输入、已有工具资源、中间结果临时决策。比如让 Agent 做一份市场调研它可能要先去搜索发现某个数据缺失再决定打开另一个数据源或者主动问用户要一份补充资料。这个过程的步骤数不固定工具组合不固定所以才需要“规划能力”。长期自治型更靠近无人值守Agent 放在后台按小时甚至按天循环执行期间根据结果自行调整策略。这类场景对记忆、审计、权限控制要求最高也最容易失控。我的建议是哪怕最终目标是长期自治第一版也先按“固定流水线动态规划”起步先把业务闭环跑通再逐步放开自主性。1.2 成本、延迟和错误率要先算账接业务前我会先算三笔账token 成本、延迟成本、错误代价。token 账很好算。一次简单的 Agent 任务平均至少三次模型调用一次拆解规划一次选择动作一次结果总结。假设每次输入四千 token、输出八百 token那光一次任务就是一万四左右的 token。一天一万次任务光 token 消耗就上亿。放到主流大模型 API 上按中间价位估算一个月下来的成本相当吓人。这不是说不能用而是说很多团队在 Demo 阶段没算过这笔账上线以后才发现单个任务毛利是负的。延迟账同样容易被忽略。模型 API 调用一次普遍要两到四秒一个拆成五步的任务就是十到二十秒。真实产品里用户根本等不了这么久。所以流程设计里必须有“快速路径”简单任务直接走单轮模型调用复杂任务才进入多步循环。另外前端一定要有超时和转人工的预案不能等 Agent 跑完才发现用户已经流失了。错误代价账最重要。自动扣款、删数据、发邮件这类动作错了要付的代价远高于 token 成本。做流程设计时凡是高影响操作必须加权限校验和人工确认点。不要相信模型“保证不会出错”要假设它会错并且设计一条可以兜底、可以回滚的路径。这三笔账算完很多需求自己就会退缩到合理范围内。2. 核心循环怎么搭计划、行动、观察、反思不是概念而是代码Agent 的核心循环说穿了就是四件事计划、行动、观察、反思。我之前在做 Demo 的时候以为把四段概念写进提示词就够了后来发现完全不是这么回事。概念写在提示词里模型确实会照着做但出了问题你根本没法定位因为它每一步都混在同一大段文本里。真正工程化的做法是把这四件事变成数据结构、函数和执行日志。2.1 ReAct 思路的工程化骨架现在主流 Agent 框架基本都吸收了 ReAct 的思路先决定做什么执行看结果再决定下一步。我建议你不管用什么框架都先搭这样一个最小可用骨架def run_agent(goal, tools, memory): # 1. 初始规划把目标拆成若干子任务 plan create_initial_plan(goal) # 2. 循环执行直到所有任务完成或触发终止条件 while not is_finished(plan): # 按依赖关系取下一个可执行的任务 step select_next_step(plan) # 模型决策这个步骤该调用哪个工具、传什么参数 action decide_action(step, tools, memory) # 执行工具并得到观察结果 observation call_tool(action) # 记录完整上下文供反思和后续规划使用 memory.append(step, action, observation) # 根据观察结果决定是否重新规划 plan maybe_replan(goal, plan, memory) return summarize(plan, memory)这个骨架的关键点在于模型的能力被限制在decide_action和maybe_replan两个出口里。它不再需要“从头到尾自由发挥”而是每次只做一个小决策这个决策是结构化的可以被记录、被验证、被回溯。后面调试的时候你可以直接看某一步模型选了哪个动作、为什么选而不是面对一整篇难以回看的对话。2.2 任务分解与依赖关系把计划当成数据结构很多 Agent 效果不稳定根本原因是没有把“计划”当成数据结构来管理。模型给出的计划如果只是一段自然语言那执行器根本不知道哪一步该先做、哪一步可以并行、哪一步失败了会影响哪些后续任务。我建议把计划建成一个任务列表每个任务带上类型、依赖、参数和验收条件。举个例子{ id: step_3, type: search, depends_on: [step_1, step_2], params: { query: user_request_keyword, top_k: 5 }, accept_criteria: 返回不少于3条可用信息 }有了depends_on执行器才能正确调度没有依赖的任务可以并行执行有依赖的任务必须等前置成功。更重要的是当某一步失败时你可以清楚地知道哪些下游任务会被影响而不是让整个 Agent 从零开始再来一遍。这个结构也让“人工介入”变得简单你可以让系统在指定步骤停下由人来填入结果再把结果交还给流程继续跑。2.3 反思不是可选的结果校验与自纠错我在实际项目里吃过最大的亏就是让 Agent “做完就算完”没有结果校验环节。模型经常自信地认为任务已经完成实际上工具调用失败或者返回了空数据。所以循环里必须加一个validate层对观察结果做非空判断、格式校验、状态码检查。如果结果不满足预期就让模型再规划一次但要严格控制次数。重试不能无限。我的习惯是给每个步骤设置最大重试次数一般是两到三次。超过次数就不再让模型继续折腾而是转入人工处理或者直接返回“当前目标无法完成”。另外重新规划也要设置全局上限。我见过一个 Agent 在同一个问题上反复修改计划足足循环了十几次最后既费钱又耗时。给循环加一个硬性终止条件和给它加业务规则一样重要。3. 记忆与上下文把“聊天记录”升级成“结构化状态”AI Agent 开发流程里记忆是最容易被低估的一层。最初我的做法很粗放把整个对话历史一股脑塞进上下文然后让模型自己找信息。结果上下文越来越长响应越来越慢模型还经常抓错重点。后来我把记忆拆成短期上下文和长期记忆两层分别处理整个系统才稳定下来。3.1 短期记忆不是所有历史都值得进上下文短期记忆的本质是“这一次任务执行过程中需要用到的最新信息”。它不应该是无脑的历史拼接而应该是“近几轮消息 历史摘要 关键变量”的三段式组合。近几轮消息保持原样因为模型需要理解最新的语境再往前的历史压缩成一段摘要避免长度无限膨胀关键变量比如用户姓名、订单号、当前所在步骤单独用结构化字段保存。这里的取舍逻辑很直接。模型对超长上下文的注意力是会被稀释的塞进一万字的聊天记录它可能连用户刚说的“不要了”都看不清。你把它整理成“用户当前意图取消订单订单号SO20240101相关历史昨晚已咨询过物流延迟”模型反而回答得更准。所以记忆整理不是损耗而是提高信噪比。3.2 长期记忆向量库加结构化标签而不是全文堆砌长期记忆用于跨会话记住用户偏好、业务规则和历史结论。很多人一听长期记忆就想到向量数据库把聊天记录全存进去然后做相似度检索。这能用但效果不稳定。向量检索对“语义相近”敏感对“时效性”和“事实准确”不敏感它很可能把三个月前用户说过的旧偏好当成现在的要求。更稳的做法是把长期记忆拆成一条条“事实”每条事实带类型、内容和元信息。比如用户偏好晚八点后配送就存成{ type: user_preference, content: 用户偏好晚八点后配送, source: conversation_20250110, timestamp: 1736496000, status: active }读取的时候不仅要做向量相似度检索还要加上类型过滤、时间衰减、状态过滤。伪代码如下memories vec_search(query, top_k20, where{type: user_preference, status: active}) memories.sort(keylambda m: m.score * decay(m.age))这样排序靠前的是“语义相关且最近确认过”的事实。过期信息被自动降权而不是跑出来干扰当前决策。3.3 记忆被滥用的典型现象旧信息覆盖新意图我调试过好几个越用越乱的 Agent最后发现问题都出在记忆写入太随意。模型把用户随口一句话当成长期偏好把临时场景当永久规则于是下一次对话时Agent 因为一条过期偏好拒绝了用户的真实指令。这种问题的修复方式不是换更好的模型而是控制写入只有系统判定为“可复用事实”的信息才允许进入长期记忆普通对话内容最多留在短期摘要里。另一个常见问题是记忆冲突。用户在 A 会话里说喜欢某个品类在 B 会话里又明确表示不需要了。旧记忆没失效新记忆又写入模型检索到两条矛盾事实后开始左右摇摆。我给这类 Agent 定的规则是同一类型、同一主体的事实默认以时间戳新的为准如果要覆盖旧值必须把旧值标记为inactive。记忆不是无限累积它和业务系统里的配置一样也要有版本、有状态、有清理机制。4. 工具调用的成败藏在“工具描述”和“错误返回”里Agent 能不能落地很大程度取决于工具调用做得好不好。模型再聪明如果工具描述写得含糊参数定义不清错误信息又不可读它就会开始瞎猜。这一块我认为是 AI Agent 开发流程里最值得投入精力的工程环节因为它直接影响模型的上限。4.1 工具描述怎么写模型才不瞎猜给模型用的工具描述和给开发者看的 API 文档是两回事。开发者看文档能忍受抽象术语模型不会。它只会根据描述里的字面信息决定怎么调用所以工具名、参数名、参数描述要尽量贴近业务语言并且给出示例。举个例子{ name: search_order, description: 按订单号或手机号查询订单状态订单号以SO开头手机号须为11位, parameters: { order_id: { type: string, description: SO开头的订单号示例SO20240101 }, phone: { type: string, description: 11位手机号示例13800138000 } } }这里的关键是给出“示例值”。模型在生成参数时会参考描述里的示例格式而不是自己编造一套。另外工具数量要克制。如果一个 Agent 同时挂着几十个工具模型选择出现混淆的概率会明显上升。我的经验是单次决策可见的工具最好控制在二十个以内超出部分按领域分组先让模型挑小组再在小组里挑具体工具。4.2 错误信息也是工具的一部分把异常返回给模型当观察结果初学者最容易犯的错是工具抛异常后直接让 Agent 看一个 stack trace。模型根本看不懂那段堆栈它还很可能一本正经地编一个错误原因然后继续走错路。正确的做法是在工具内部捕获异常转换成模型能直接消费的结构化信息。{ status: failed, code: INSUFFICIENT_STOCK, message: 商品当前剩余2件用户申请5件, suggestion: 询问用户是否接受拆单或换成同品牌替代品 }模型看到这样的返回就知道发生了什么、下一步可以考虑什么。它可以把“库存不足”当成观察结果重新走规划分支而不是原地重复尝试同一个动作。这一点听着简单但对 Agent 成功率提升非常明显。我调过好几个项目把错误返回改成这种格式之后无效重试率直接降了一半。4.3 工具权限与重试红线别把安全寄托在提示词上工具调用这一层必须做权限控制不能只靠提示词里写一句“请勿重复扣款”。凡是涉及扣款、删除、发送等高风险操作都要在代码层面拦一道。我的做法是每个动作经过一个check_permission函数判断当前用户、当前场景是否有权限执行高风险动作必须进入人工审批队列。同时每个写操作要带幂等键同一笔业务重复执行时只生效一次。重试次数也要在工具层限制。比如订单创建接口最多允许 Agent 重试两次超了就进入人工处理。模型在规划时再想重试网关直接返回“REQUST_FAILD_TOO_MANY_RETRIES”它只能换个思路。这些控制不是限制 Agent 的能力反而是让它在一个安全范围内自由发挥。没有边界的能力在生产环境就是事故。5. 评测驱动迭代没有回归集改 Prompt 就是在裸奔很多开发者的迭代方式是这样的发现 Agent 某个回答不对马上改提示词跑几个手头用例感觉“好了”然后就上线。这种做法在单轮对话时代勉强凑合在 Agent 这种多步、多工具的系统里基本行不通。你修好 A 场景很可能又把 B 场景弄坏而且你自己都毫无察觉。所以我把评测当成 AI Agent 开发流程的主循环每次改动必跑回归集。5.1 构建回归测试集用例分桶打分不靠感觉回归测试集的用例不能随便找几个问题凑数。我会按任务类型、难度、工具依赖、陷阱类型四个维度给用例打标签。任务类型包括单轮问答、多步查询、跨工具操作等难度分为简单、中等、困难工具依赖说明这个用例会用到哪些工具陷阱类型可以是“信息缺省”“歧义表达”“矛盾指令”等。每个用例至少包含输入内容、预期路径、预期结果、成本上限。打分也不要凭感觉。我通常用三档评分结果正确、路径规范、资源合理。结果正确指最终目标达成路径规范指是否走到了预期工具、有没有绕弯资源合理指 token 消耗和步数是否在预算内。三档都满足才算是“完美通过”。只要有一个用例回归出问题就说明这次改动影响面比想象的大应该先回退再分析根因。5.2 我看的五类核心指标评测只看正确率不够尤其是越权操作这种错误在测试集里可能根本触发不了。所以我还会记录下面这些过程性指标指标含义我关注它的原因目标完成率最终成功完成目标的比例最直观的效果指标平均步数每个任务经历多少轮工具调用步数越多越可能绕路无效工具调用率调用失败或对目标无帮助的比例反映工具选择是否准确人工介入率多少任务需要人工接管过高说明自动性不足平均耗时至P90耗时任务完成时间分布影响真实产品体验我特别强调无效工具调用率。一个 Agent 可能最终完成了任务但它中间调了五次无关工具、重试了三次这其实是“假成功”。这类任务一旦放到高并发生产环境成本和延迟马上会暴露问题。所以评测集不仅要测“能不能到终点”还要看“走的路是不是合理”。5.3 一个失败用例的回放根因分析有一次我调一个模拟客服 Agent新版本引入了“查询跨平台比价”功能。上线前回归发现订单查询类任务的完成率从 85% 掉到 70%。表面上看是新增功能影响了原有模块。用日志回放后发现模型在订单查询子任务里拿到空结果后不是重新搜索而是直接跳到“创建新订单”。根因是工具返回的空结果信息不明确模型误以为订单不存在而且重新规划触发条件太宽模型一遇到异常就放弃当前路径。修复动作有两个一是把空结果改成结构化错误返回代码标为ORDER_NOT_FOUND并附带“建议检查订单号或手机号后重试”二是把重新规划次数从无限制改成三次。改动后跑回归集订单查询完成率恢复到 86%跨平台比价功能也保持住了。这类问题如果没有回归集和日志回放几乎不可能定位。6. 上线只是开始日志、灰度、人工兜底缺一不可Agent 上线和普通服务上线不一样。普通服务的异常是明确的报错Agent 的异常可能是“结果看起来正常但路径完全不对”非常隐蔽。所以我把它当成一个带行为边界的系统来运营而不是一个接口来发布。日志、灰度和人工兜底这三件事在第一天就要设计好。6.1 给每次运行留一份可回放的“病例”我给每个 Agent 运行都记录结构化日志包含目标、计划、每一步的动作、观察结果、最终结论、模型版本、耗时、token 消耗等字段。大致结构是这样{ run_id: run_20250110_10001, goal: 查询订单SO20240101的物流状态, plan: [search_order, track_logistics], actions: [ { step: search_order, tool: search_order, params: {order_id: SO20240101}, observation: {status: ok, data: {...}} } ], human_review: false, token_count: 3200, latency_ms: 2800 }这套日志最大的价值是支持“回放”。当线上用户投诉某个回答不对我可以直接把那次运行的所有决策路径拉出来看模型看到了什么、选了哪个工具、工具返回了什么、它为什么走向错误分支。没有这份记录排查 Agent 问题只能靠猜基本等于大海捞针。6.2 提示词和配置要版本化并灰度发布很多人把提示词改完直接覆盖线上这是 Agent 上线后的大忌。提示词、工具描述、参数配置都应该有版本号运行时从配置中心读取指定版本。模型 API 本身可能更新我们的提示词也会调所以日志里必须同时记录“应用版本提示词版本模型版本”哪一环变化都能追踪。灰度方面我习惯先放 5% 的流量到新版本观察主要指标没有退化再扩大到 50%最后全量。这个策略一点都不新鲜但很多团队没有把它用在 Agent 上。原因是他们觉得 Agent 是“智能”的改动应该比较安全。实际上模型的多步决策放大了微小改动的风险一个工具描述措辞调整可能让原本正常的流程绕半个圈子。所以灰度不是可选项。6.3 把“不确定”显式交给人工置信度不是玄学再强的 Agent 也有把握不准的时候。我的原则是不确定就不要硬答。系统里设置两个触发人工的条件一是模型自评置信度低于阈值二是动作命中了高风险列表。满足任一条件Agent 就返回一个“NEED_REVIEW”状态把当前决策路径、备选方案、相关证据一并交给人工审核。人工介入后产生的决策可以回写进记忆或配置作为 Agent 后续学习的参考。这一步看起来慢但对长期运营非常重要。它既保证了关键业务的安全性又让 Agent 的边界在真实反馈里一点点变清晰。上线初期的目标不是“零人工介入”而是“所有介入都发生在这个兜底机制之内”。7. 一条贯穿始终的原则确定性优先模型只做决策最后说一条我每次带新项目都会反复强调的原则能确定性写死的东西就不要交给模型自由发挥。状态机、任务依赖、权限校验、重试上限、日志记录这些都应该由代码控制模型只负责少数几个需要语义理解的决策点比如理解用户意图、选择合适工具、判断结果是否满足要求。7.1 确定性代码管流程模型管判断我见过不少 Agent 代码整个流程跑在提示词里模型“规划”出来的步骤又被拿去执行但没有人知道每一步是否合理。这种方案最致命的问题是你不清楚它下一秒会干什么。把流程主干用确定性代码定死之后模型的行为空间是受约束的它只能在我给的工具里选、只能在我设定的步骤间跳转、只能在重试上限内纠错。它仍然有自主性但它的自主性是被护栏框住的。这种设计还有一个好处就是新人接手快。看到run_agent的循环骨架看到任务列表的depends_on看到日志里的每一步动作不需要读完全部提示词也能理解系统在干什么。确定性代码是系统的骨架模型是嵌入骨架里的判断单元。如果反过来整个项目会迅速变成一团难以维护的“黑话协议”。7.2 先把“能接受失败”的任务跑起来如果你正在计划做第一个 Agent 项目我的建议是别选支付、医疗、法律这类高风险场景起步。找一些即使失败也容易兜底的业务比如内部知识问答、客服辅助、日报整理、数据查询先把流程、评测、日志、人工兜底这条链路跑通。这些场景允许 Agent 犯错你能积累到真正有价值的调试经验。等评测集已经能抓住大部分回归问题再逐步往高影响业务上扩展。我最近带团队做模拟项目 X 时第一周基本没有调提示词时间全花在搭测试集、跑日志回放、定义工具协议上。后面真正迭代起来我才发现这些“慢功夫”才是最省时间的部分。如果你也在做 Agent建议把这条开发流程尽量走完整边界、循环、记忆、工具、评测、灰度、人工兜底。越早补齐后面越省心。