news 2026/10/25 18:24:16

AI Agent工程实现的七要素与七个决策点全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Agent工程实现的七要素与七个决策点全解析

前两天一位读者给我发了段 AI Agent 的 Demo,很兴奋地说他能让模型自己调用搜索工具、写文件、做表格了。结果我问了一句"你跑过几个任务",他沉默了。换一个任务就崩,中间步骤出错没人发现,模型甚至会无视工具返回自己编答案。这个场景我这两年看了太多次:AI Agent 的工程实现,难点从来不在"接上大模型 API",而在把一个一次性的 LLM 调用,变成一个有规划、有记忆、有反馈、有终止条件的闭环系统。

我习惯用一套框架来拆解 Agent 的工程实现,就是标题里说的:七要素和七个决策点。七要素帮你把"一个 Agent 到底由哪些部分组成"想清楚,七个决策点是落地时每个部分都必须做的关键选择,从"用什么循环范式"到"怎么判断它是不是真的完成了",环环相扣。这篇文章就把这套框架完整展开,适合正在搭 Agent、或者搭完发现不稳定的同学参考,也适合准备做 Agent 产品化的人用来做技术选型。

1. 先把七要素过一遍:Agent运转的工程骨架

1.1 Agent是"感知—规划—行动—观察"的循环,不是一次对话

很多人对 Agent 的理解停留在"能调用工具的 ChatGPT"。这个理解不能说错,但它缺少一个关键视角:Agent 的本质是循环。一次对话只有一轮问答,Agent 会在"思考—调用工具—看结果—再思考"这个圈里转很多圈,直到拿到可验证的结果或到达终止条件。

打个比方,把 Agent 比作一个刚入职的实习生:大模型是实习生的大脑,负责想问题;工具是电脑和办公软件,负责干活;记忆是工作笔记,负责记住前面做了啥;观测反馈是领导给的回应,负责告诉实习生这次干得对不对;循环控制是项目经理,负责喊停或调整方向。如果只给实习生一个大脑和一堆软件,却不给他反馈回路,他就不知道错在哪,也不知道什么时候该停。

1.2 七要素清单与工程对应关系

不同资料对 Agent 要素的分法不太一样,有的说四大要素,有的说五大组件。我这里用工程落地视角把它拆成七块,每一块都对应一个具体的系统模块:

要素核心职责工程落地形态
模型推理基于当前信息和目标做决策、输出思考过程LLM 接入层、Prompt 编排、思维链
规划把目标拆成步骤、决定下一步动作Planner 模块、任务队列、策略选择
记忆保存上下文和跨会话经验消息列表、摘要、向量检索
工具与外部世界交互的能力Function Schema、工具注册中心
行动执行发起工具调用、处理参数Executor、API 网关、并发控制
观测反馈拿到工具结果并判断是否符合预期结果解析、校验、异常处理
循环控制决定继续、重试还是终止步数上限、早停、重试策略

这张表的排序是按一个 Agent 实际跑起来的时间顺序来的:先有推理,再做规划,查记忆,选工具,执行动作,观察结果,然后循环控制决定要不要再来一轮。任何一个环节缺失,Agent 都会以某种方式"半残"——只是很多项目缺了某个环节后,只在特定任务上暴露出问题,所以没被及时发现。

1.3 为什么不是"四大要素",而是七要素

很多人提到 Agent 必说记忆、规划、工具、行动四大要素,这没错,但在工程上只讲四要素是不够用的。模型推理和观测反馈往往是决定成败的隐藏变量:模型推理的 Prompt 写得不好,模型每一步都在瞎猜;观测反馈缺失,工具已经返回错误了,模型还接着往下跑。循环控制则是所有基础设施里最容易被忽略的——不加max_steps的 Agent,跑偏之后能烧掉你一整天的 token 额度。

所以我把七要素当作一张工程检核表。每做一个 Agent 项目,就对着表格过一遍:这块有没有?谁负责?如果不加会出什么问题?下面的七个决策点,就是这张检核表落到代码里最关键的七个岔路口,从循环范式、模型选型,到上下文记忆、工具协议、规划策略,再到终止容错和评估观测,每一个都需要明确拍板。

2. 决策点①:循环范式设计,先想清楚Agent怎么转

2.1 三种循环范式,从简单到复杂

决策点①回答的问题:给定任务之后,Agent 内部用什么结构运转?

最基础的范式是单次调用,模型拿到用户问题和工具列表,一次性给出回答。适合简单问答,但严格来说这不叫 Agent,因为没有任何环境交互,工具也没有真正被用起来。

第二种是ReAct(Reasoning + Acting)循环。模型输出一段思考,然后输出一个动作(比如调用工具),系统执行动作后把观察结果放回上下文,再让模型接着思考。这是目前最流行的范式,适合大部分工具调用场景。它的核心思想是"边想边做",每一步推理都基于上一步的实际观察,而不是预先编好的剧本。

第三种是Plan-then-Execute。模型先输出一份完整计划,把任务拆成若干子步骤,然后按计划逐步执行。这种范式适合步骤多、依赖关系复杂的任务,因为先规划可以避免模型走一步看一步导致的路径发散。

选择策略并不复杂:任务步骤数小于 3 且工具简单,直接用 ReAct;步骤多、依赖关系复杂,用 Plan-then-Execute;任务结果需要反复推理验证,可以在 ReAct 基础上加反思(Reflexion)。别一上来就上重型框架,plan 本身也会消耗 token 和延迟,很多业务场景根本撑不住那套复杂编排。

2.2 ReAct循环的最小可运行骨架

ReAct 的工程实现可以很简单。下面这个骨架是我常用的起点,去掉所有业务细节之后核心逻辑只有十行左右:

MAX_STEPS = 10 system_prompt = """ 你是一个可以调用工具完成任务的AI助手。 请严格按照下面的格式输出: 思考:对当前任务的简要分析 动作:工具名(参数) 如果没有更多工具需要调用,直接输出:最终回答:xxx """ def run_agent(task, tools, llm): messages = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": task} ] for step in range(MAX_STEPS): response = llm.chat(messages) action = parse_action(response) # 解析动作,返回None则代表最终回答 if action is None: return response result = execute_tool(action, tools) # 调用工具并捕获异常 messages.append({"role": "assistant", "content": response}) messages.append({"role": "user", "content": f"工具返回:{result}"}) return "超过最大步数,任务终止"

这里面最关键的不是代码量,而是"工具返回被当作用户消息放回上下文"这个动作。它让模型能够看到自己行动的后果,然后继续推理。很多初学者会在这里犯错:工具调用结果只存到变量里,没有拼回消息列表,模型到下一步就"失忆"了,这属于七要素里的反馈回路没接通。

3. 决策点②:推理模型选型,Function Calling是硬门槛

3.1 为什么模型选型决定Agent的天花板

同一个 Agent 框架,换一个模型,效果可能天差地别。原因是 Agent 对模型有三重考验:

第一,模型能不能根据工具描述生成"符合规范"的工具调用参数。很多通用对话模型能理解工具意图,但输出的参数格式乱七八糟,得靠正则和修复脚本去捞,极其脆弱。

第二,模型在长上下文里能不能保持一致性。Agent 每跑一步上下文都在变长,如果模型在 20k token 后就"迷糊",那任务超过五步基本就废了。

第三,模型愿不愿意在收到工具返回后改变自己的结论。很多小模型会无视工具返回,坚持输出自己原本编造的内容,这是最可怕的——工具已经明确说"查无此人",模型还在煞有介事地介绍这个人的背景。

3.2 模型能力对比与选型建议

拿强 Function Calling 模型和通用对话模型对比一下:

能力维度强 Function Calling 模型通用对话模型
工具调用输出直接输出结构化 JSON经常输出自然语言,需强解析
长上下文稳定性较好靠窗口截断勉强维持
对工具结果的遵从度高低,容易无视返回继续编
成本高低
适合场景生产级 Agent原型验证

我的建议是:先跑通,再换。别在选型阶段纠结"哪个模型最好",先用一个主流模型把框架跑起来,后面用同一套评估数据(对应决策点⑦)去对比替换。选型还要算成本账:Agent 的 token 消耗远高于普通对话,任务循环会放大模型成本。一个 20 步的 Agent 任务,可能要烧掉 5 到 10 万 token,模型单价差几倍,总成本会被循环放大到完全不同的数量级。等你把架构跑顺了、评估指标有了,再回来做性价比优化,才是正路。

4. 决策点③:上下文预算与记忆分层,决定任务能做多深

4.1 先用公式估算成本

Agent 的上下文管理是工程实现里最容易踩坑的部分,而且踩坑的后果很隐蔽——不是直接报错,而是"任务做到一半,模型开始胡说八道"。先把账算清楚:

单轮 Agent 调用开销 = 系统提示词 + 工具定义 + 历史消息 + 模型输出。

假设系统部分 3000 token,每轮"思考 + 调用"输出约 1000 token,工具返回约 1500 token。如果完全不做处理、保留全部历史,第 10 步的模型输入 ≈ 3000 + (1000 + 1500) × 9 = 25500 token,累计 10 步的输入 ≈ 3000 × 10 + 2500 × 45 = 142500 token。也就是说,一个 10 步的简单任务,输入侧累计就能突破十四万 token,比一次普通对话高出两个数量级。

这不是危言耸听,而是每个做 Agent 的人迟早要撞上的硬约束。上下文窗口有限、成本有限,所以上下文管理不是可选项,而是第一优先级。

4.2 记忆分层的工程形态

面对这个约束,我把记忆分成三层:

  • 短期记忆:最近几轮消息完整保留。这是模型推理的主要依据,丢失了它,模型立刻失忆。
  • 长期记忆:把较早的历史压缩成摘要,或者写入向量库,需要时召回相关片段。这是跨会话经验存储的地方。
  • 工作记忆:当前子任务的中间状态(比如规划里的 JSON 变量、任务目标、已完成步骤清单)单独存放,避免一股脑塞进对话 History。

分层之后,最常用的是"滚动摘要 + 最近完整保留"策略。核心逻辑是这样的:

def summarize_and_roll(history, summary, keep_last=4, summarize_fn=None): """ history: 完整消息列表 summary: 上一次压缩后的历史摘要 keep_last: 需要完整保留的最近轮次数 """ if len(history) <= keep_last * 2 + 1: return summary, history old = history[:-(keep_last * 2)] # 需要压缩的旧消息 recent = history[-(keep_last * 2):] # 最近消息,完整保留 new_summary = summarize_fn( f"已有摘要:{summary}\n新内容:{'\n'.join(m['content'] for m in old)}" ) return new_summary, recent

这个函数每次在上下文快要溢出时调用,把旧消息压缩成一段摘要,最近的对话保持原样。它的优点是实现成本低,缺点是摘要会丢掉细节。实战中,任务的核心目标、已完成的步骤清单、关键中间产物这三类信息要永远保留,宁可从别的地方省 token,也不能丢这三样。

4.3 检索召回的取舍

再进一步就是向量库召回。任务做到后面,Agent 可能需要回忆很多步之前的一个数据,靠自然语言摘要早就糊了,这时就要从向量库里按相关性把原片段捞回来。

但检索召回有几个现实问题:召回结果质量取决于 Embedding 模型和分块方式,分块太大没用,太小语义割裂;召回条数控制不好还会污染上下文——本来是来帮忙的,结果塞进一堆无关片段,模型更晕。我的经验是:召回条数控制在 3-5 条,每条长度控制在 300 token 以内,并且召回内容要标注来源时间点,让模型知道哪段历史对应哪一步。长期任务的上下文预算分配,大致可以参考这个比例:

上下文项目预算占比
系统提示词 + 工具定义20%-30%
最近的对话历史20%-30%
检索或摘要的历史10%-20%
当前任务、规划、工作记忆剩余空间

5. 决策点④:工具协议设计,Agent的手脚必须可控

5.1 工具描述怎么写,模型才看得懂

工具协议,简单说就是告诉模型"你有什么工具、工具能干什么、参数是什么"。工程上最通用的是用 JSON Schema 描述。这里有个反直觉的点:给模型看的工具描述,和给你同事看的 API 文档完全是两回事。API 文档追求准确,工具描述追求"让模型在正确时机用正确参数调用"。

一个搜索引擎工具的 Schema 示例:

{ "name": "web_search", "description": "在互联网上搜索公开信息,返回标题和摘要列表。当用户需要最新资讯、未知事实或需要核实信息时使用。", "parameters": { "type": "object", "properties": { "query": { "type": "string", "description": "搜索关键词,尽量具体,一次只搜索一个主题" }, "max_results": { "type": "integer", "default": 5, "minimum": 1, "maximum": 10 } }, "required": ["query"] } }

关键是 description 里要写清楚触发条件——什么时候该用这个工具。很多工具描述只写"搜索互联网",模型不知道该在什么场景下调用,结果该搜的时候不搜,不该搜的时候瞎搜。参数描述也要写取值范围和默认值,减少模型生成非法参数的概率。

5.2 工具返回要结构化,错误也是信息

工具返回值我强烈建议做成结构化的 JSON,统一包含status、data、error三个字段。这样模型每次看到的反馈格式都是一致的,容易形成稳定的推理模式。

更重要的细节是错误处理。工具调用失败时,不要把原始异常堆栈直接塞给模型。模型看到一堆ConnectionError、TimeoutError的英文堆栈,根本不知道该做什么。正确的做法是把异常整理成"错误摘要 + 可能原因 + 建议",例如原始异常是HTTP 503,转成:

{ "status": "error", "error": "服务暂时不可用,可能是限流或后端过载", "suggestion": "等待后重试,或更换一个搜索关键词" }

这样模型就能把"错误反馈"当成下一步决策的输入:重试、换参数、还是换工具。这一步不做好,Agent 第一次碰到异常就会开始编答案。

5.3 工具协议三个高频坑

  • 工具太多,Schema 压垮上下文。接了 30 个工具之后,光工具描述就能吃掉小一万 token。解法是按任务动态加载,只把当前任务可能用到的工具放进系统提示词,其他放工具注册中心备用。
  • 枚举值说不清,模型反复生成非法参数。解法是把可选项写进 Schema 并给 default,还不行就在工具执行层做参数校验,非法参数直接返回"参数不合法,可选值为 xx",让模型重新生成。
  • 工具执行超时没有兜底。大多数工具调用是外部 HTTP 请求,不设超时会卡住整个循环。每个工具调用都必须设置超时,超时也算一次正常观察,把"超时了"这个信息返回给模型,让它自己决定是重试还是换路。

6. 决策点⑤:规划策略,复杂任务要先想再做不硬闯

6.1 什么时候需要规划

不是所有任务都需要规划。如果任务只调一次工具就能完成,硬上 Plan-then-Execute 纯粹是浪费 token 和延迟。我的判断标准是:任务包含多个互相依赖的步骤、需要多个工具协作、或者需要对中间结果做条件分支时,才考虑规划。3 个步骤以内的任务,直接 ReAct;超过 3 步且步骤顺序影响结果,再上规划。

还有一种隐性的信号:如果同一个 ReAct 循环里,模型反复在里面绕圈子、做了大量无用动作才到达终点,那说明任务本身就值得先规划一下,而不是让模型走一步看一步。

6.2 Plan-then-Execute 落地细节

Plan-then-Execute 的核心是两步:先生成计划,再执行计划。

生成计划时,Prompt 要明确要求模型"只输出计划,不要执行任何操作",并且按 JSON 数组输出,方便程序校验:

[ { "step": 1, "goal": "获取最新文章列表", "tool": "fetch_articles", "success": "返回状态为ok且包含文章数组" }, { "step": 2, "goal": "按发布时间排序并输出摘要", "tool": "summarize", "success": "输出包含3条文章摘要" } ]

计划生成后,脚本要做一次合法性校验,比如检查计划的工具名是否真实存在、必填参数是否有值。这一步很多人省略,结果模型生成一个调用不存在工具的计划,执行阶段第一轮就崩。

执行阶段的关键是把计划列表放进消息上下文,每完成一步就在计划上标记完成情况。模型根据已完成标记决定下一步是继续、修正计划还是收尾。注意,计划不是不可变的——执行中遇到工具返回和预期不符,要允许模型修改计划。很多实现失败,就是因为执行器死板地按计划走,一步出错就整个卡死。

6.3 失败后的反思机制

对于结果需要反复验证的任务,我强烈建议在 ReAct 或 Plan-then-Execute 之上加一层反思(Reflexion)。机制很简单:任务失败后,让模型对比"预期结果"和"实际结果",写一段反思文字,指出失败原因和下次要改什么,然后把这端反思放进下一轮尝试的上下文。

比如一个写爬虫 Agent 失败后,反思可能是:"我上一轮忘了先检查响应状态码就直接解析内容,导致拿到空数据。下一步要先打印 status_code 并判断是否为 200。"这种反思对模型的修正效果,比单纯把错误返回给它要好得多,因为它是模型自己产出的、用自己语言表达的结论。

7. 决策点⑥和⑦:终止容错与评估观测,这是上线前的两道关

7.1 终止条件:max_steps不是万能药

循环控制里最简单的实现是设一个MAX_STEPS,我一般设 15 左右。但如果模型连续生成非法 JSON、parse 失败、或者反复输出同样的话,它会在这个上限内原地打转,把预算烧光,最后还给你一个"超过最大步数"的失败。

所以除了硬上限,还要有早停机制。两种方式结合:第一,模型判断任务完成时输出明确的"最终回答"标记,系统识别后结束;第二,工具结果里出现明确的"任务完成"信号时,系统直接终止,不等模型自己宣布。第二种尤其重要,因为模型容易过早宣布完成——它觉得差不多行了,但系统侧校验发现最终答复缺了任务要求的必要字段,比如没有给出具体的检索结果列表。系统侧校验不过,就退回继续循环,这是防止模型"偷懒"的有效手段。

7.2 容错降级三层设计

容错设计我习惯分三层:

第一层,输出解析。模型输出的工具调用 JSON 不合法时,先做修复——比如提取被 Markdown 代码块包裹的 JSON、补上缺失的右括号。修复不了,就把"输出格式不合法,请严格按 JSON 输出工具调用"作为反馈返回,让它重新生成。

第二层,工具异常。照第 5 章说的,把异常转成结构化错误反馈,模型基于错误反馈重新决策。这一层已经能覆盖大部分偶发故障。

第三层,全局降级。连续失败超过 3 次后,不再重试,直接进入"安全答复"——比如告知用户暂时无法完成任务、返回手上已有的部分结果。这一步是为了止损,避免一个注定失败的任务把一天的 token 额度烧完。

还有一个部署层面的提醒:如果你的 Agent 跑在 Django 这类 Web 框架后面,工具调用务必走异步任务队列,别把一个十几步的长循环直接塞进请求线程,一个任务卡住,整个 Web 服务的线程池就堵了。编排层的实现语言也会影响吞吐,我见过不少团队用 Python 做原型、用 Rust 或 Go 重写执行层来扛并发,这是一条很常见的工程路径,但前提是先把上面的逻辑跑通。

7.3 评估与可观测性

最后是评估和可观测性,这是我判断一个 Agent 能不能上线的底线。先回答三个问题:

  1. 任务成功率是多少?
  2. 一次成功平均花了多少步、多少钱?
  3. 失败的任务挂在哪一步?

没有这三个数字,你在优化 Agent 时就是在盲调。所以从第一天就要做两件事:一是记录完整 trace,每个 step 的模型输入、模型输出、工具调用、工具返回、耗时、token 数全部落日志;二是准备一批固定的评估任务,至少 30 个能代表真实业务场景的任务,每次修改 Prompt、换模型、调参数之后,都跑同一批数据,按成功率、平均步数、平均成本三个指标对比。

基于 trace 回放,你会很快发现问题的分布:是模型不理解工具描述,还是工具返回格式太乱,还是终止条件太松导致跑飞。有了数据支撑,前面的六个决策点才能逐一定位调优。


还是回到开头那位读者。我把这套框架丢给他之后,他把自己的 Demo 按七要素过了一遍,发现最缺的既不是模型也不是工具,而是观测反馈和循环控制——工具返回了他没解析,模型编错了没人发现,循环也没有终止条件,最后当然一跑就崩。我做 Agent 工程这两年最大的体会就是:大多数"Agent 不稳定"的问题,都能在七要素和七个决策点里找到原因。现在你让我评估一个新框架,我只问两个问题:它能不能清楚记录每个 step 的 token 消耗和失败位置?它遇到异常会怎么降级?这两个问题答不上来,再炫的功能我也不敢上生产。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/25 17:59:02

大模型API接入省钱稳定方案:自建网关与多供应商降级实战

做服务端这块以来&#xff0c;最让我头疼的采购单不是服务器&#xff0c;而是大模型 API 的账单。官方接口质量确实有保证&#xff0c;可价格明明白白放在那里&#xff0c;按 Token 计费&#xff0c;量一上来就肉疼&#xff1b;直接连官方接口又经常遇上限流和超时&#xff0c;…

作者头像 李华
网站建设 2026/10/25 17:52:29

C#实现STEP文件解析器:从词法扫描到拓扑提取的完整指南

简介&#xff1a;一份面向计算机相关专业本科毕业设计的C# STEP文件解析器项目源码&#xff0c;针对STEP三维模型数据交换格式的读取与解析需求&#xff0c;适合需完成文件解析类课题或希望掌握C#工程实践经验的学生参考。压缩包共18个文件&#xff0c;以9个cs源码文件为核心&a…

作者头像 李华
网站建设 2026/10/25 17:52:17

PaddleOCR-VL-1.5轻量版:小参数高性能OCR部署方案

1. 项目概述&#xff1a;PPIO推出PaddleOCR-VL-1.5轻量方案今天要分享的是PPIO最新上线的PaddleOCR-VL-1.5解决方案。这个版本最大的特点就是在保持高性能的同时&#xff0c;大幅缩减了模型参数规模。作为一款主打"小参数高性能"的OCR工具&#xff0c;它特别适合需要…

作者头像 李华
网站建设 2026/10/25 16:49:21

WorkBuddy与DSH本地协同工作流深度解析

1. WorkBuddy 与 DSH&#xff1a;不是“桥接”&#xff0c;而是本地智能工作流的重新定义你搜过“workbuddy-to-dsh使用教程”&#xff0c;点开一堆页面&#xff0c;发现要么是零散截图、要么是“安装Node→下载插件→配置API→完事”的四步流水账&#xff0c;再要么就是直接甩…

作者头像 李华