news 2026/10/9 0:01:48

AI Agent工程实战:从七要素到七个决策点的系统设计指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装,到后来自己拆解每一层的职责边界,踩过的坑基本都集中在几个固定的地方:循环怎么设计、工具怎么调、状态怎么管、失败怎么兜。这篇内容不打算讲概念科普,而是把 Agent 从七要素到七个决策点这条链路完整拆开,讲清楚每个环节在工程上到底要做什么选择、为什么这么选、选错了会怎样。适合已经了解 LLM 基础、准备或正在搭建 Agent 系统的开发者,也适合想搞清楚 Agent 内部到底怎么运转的技术负责人。

1. 七要素拆解:Agent 系统的最小完整单元

很多人一上来就问"用哪个框架",但框架只是外壳,真正决定系统能不能跑通的是七个核心要素是否都到位。这七个要素不是并列关系,而是有依赖顺序的,缺一个都会导致系统在某个环节卡死。

1.1 模型层:不只是选一个 LLM 那么简单

模型层是 Agent 的"大脑",但工程上要决策的远不止"用哪个模型"。你需要考虑的是:主推理模型和辅助模型怎么分工。实际项目中,我通常会把模型分成三类角色来用。

第一类是主推理模型,负责理解用户意图、规划任务步骤、决定下一步调用什么工具。这类模型需要较强的指令遵循能力和推理能力,通常选参数量较大、经过指令微调的版本。第二类是工具调用模型,专门负责把自然语言意图转成结构化的工具调用参数。有些场景下主推理模型可以直接兼任,但如果工具参数格式复杂,单独用一个更擅长结构化输出的模型会更稳。第三类是结果总结模型,把工具返回的原始数据转成用户能读懂的回复,这类任务对推理能力要求不高,可以用更轻量的模型来降低成本。

为什么要做这个分工?因为一个模型很难在所有维度上都最优。主推理需要深度思考,工具调用需要格式精确,结果总结需要语言流畅,这三个目标在训练时是有张力的。分开之后,每个环节都可以独立调优和替换,不会因为换一个模型就把整个系统搞崩。

还有一个容易被忽略的点:上下文窗口的实际可用量。标称 128K 的模型,实际能稳定利用的可能只有一半左右,因为中间部分的信息容易被"遗忘"。所以在设计时,不要把关键信息塞在超长上下文的中间位置,要么放在开头,要么放在结尾,要么通过外部存储来管理。

1.2 记忆层:短期、长期、工作记忆的三层结构

记忆层是 Agent 区别于单次 LLM 调用的核心。没有记忆,每次对话都是重新开始,Agent 就无法完成多步骤任务。

工程上我习惯把记忆分成三层。短期记忆就是当前对话的上下文,通常用消息列表来维护,直接塞进模型的上下文窗口。工作记忆是当前任务执行过程中的中间状态,比如已经完成了哪些步骤、当前卡在哪一步、已经收集到哪些信息。这部分不一定全部塞进上下文,而是用一个结构化的状态对象来管理,需要的时候再取出来。长期记忆是跨会话的知识,比如用户的偏好、历史任务的结论、领域知识库,通常存在外部存储里,通过检索来调用。

这三层的管理策略完全不同。短期记忆的关键是截断和压缩——对话太长时要决定丢弃哪些、总结哪些。工作记忆的关键是结构化——不能是一堆散乱的文本,而要有明确的字段和状态机。长期记忆的关键是检索质量——存进去容易,取出来准才是难点。

我踩过的一个坑是:早期把所有东西都往短期记忆里塞,结果上下文迅速膨胀,模型开始忽略中间的信息,任务执行到一半就"忘了"之前做过什么。后来改成工作记忆用独立的状态对象管理,只在每一步需要的时候把相关部分注入上下文,稳定性提升非常明显。

1.3 工具层:Agent 与外部世界交互的唯一通道

工具层决定了 Agent 能做什么。没有工具,Agent 只能"说",不能"做"。工具的设计质量直接决定了 Agent 的能力上限。

工具层要解决三个问题:工具怎么定义、工具怎么选择、工具怎么执行。定义方面,每个工具需要清晰的名称、描述、参数 schema 和返回值格式。描述要写得让模型能准确判断"什么时候该用这个工具",而不是靠猜。参数 schema 要严格,该必填的必填,该枚举的枚举,减少模型自由发挥的空间。

工具选择是 Agent 循环中的核心决策点。当工具数量超过十个之后,模型选错的概率会明显上升。常见的做法是分组——把工具按领域分成几组,先让模型选组,再在组内选具体工具。另一种做法是预过滤——根据当前任务状态,先用规则或轻量模型筛掉明显不相关的工具,只把候选工具给主模型选。

工具执行方面,最关键的是超时和重试策略。外部工具调用可能失败、可能超时、可能返回格式不对的数据。每个工具都要有独立的超时设置和重试逻辑,不能用一个全局配置糊弄过去。我一般会给每个工具配三个参数:超时时间、最大重试次数、失败后的降级行为。

1.4 规划层:从"想到哪做到哪"到"有章法地推进"

规划层是很多 Agent 项目最容易做薄的地方。没有规划,Agent 就是"走一步看一步",遇到复杂任务就容易迷失。

规划层的核心是任务分解和执行顺序编排。任务分解是把用户的模糊需求拆成可执行的步骤,执行顺序编排是决定这些步骤是串行、并行还是有条件分支。

工程上有两种主流做法。一种是显式规划——先让模型生成一个完整的步骤列表,然后按列表逐步执行。这种做法的好处是全局可见、容易调试,坏处是如果第一步就理解错了,后面全错。另一种是隐式规划——不生成完整计划,而是在每一步根据当前状态决定下一步做什么。这种更灵活,但容易陷入局部最优,做着做着偏离了原始目标。

我实际项目中用的是混合模式:先做一次粗粒度的显式规划,把任务分成几个大阶段,每个阶段内部用隐式规划逐步推进。这样既有全局方向,又有局部灵活性。粗粒度规划不需要太细,三到五个阶段就够了,太细反而容易因为实际情况变化而频繁调整。

1.5 执行层:循环机制的设计与边界控制

执行层就是 Agent 的"主循环",是整个系统运转的引擎。循环机制设计得好不好,直接决定了 Agent 是"智能"还是"智障"。

一个基本的 Agent 循环是这样的:接收输入 → 模型推理 → 决定动作 → 执行动作 → 观察结果 → 判断是否完成 → 未完成则回到推理。看起来简单,但每个环节都有工程决策。

循环终止条件是最关键的。不能只靠模型说"我完成了"来判断,因为模型可能会误判。我通常设三重保险:模型显式声明完成、达到最大循环次数、连续 N 次没有产生有效动作。三个条件满足任意一个就终止,避免死循环烧钱。

循环中的状态传递也很重要。每一轮循环要把哪些信息传给下一轮?全部传会导致上下文膨胀,传太少会导致信息丢失。我的做法是维护一个结构化的执行状态,每轮只把"当前步骤相关的上下文 + 全局状态摘要"注入模型,而不是把完整历史都塞进去。

1.6 反馈层:让 Agent 知道自己做得对不对

反馈层是 Agent 自我修正的基础。没有反馈,Agent 就无法判断自己的输出质量,也无法在出错时调整策略。

反馈分两种:内部反馈和外部反馈。内部反馈来自 Agent 自身的判断,比如模型对自己输出的置信度、格式校验的结果、逻辑一致性检查。外部反馈来自工具返回值、用户输入、环境变化。

工程上最实用的是结构化校验。每次工具调用返回后,不要直接把原始结果丢给模型,而是先做一轮格式和内容的校验,把校验结果作为反馈的一部分。比如调用搜索工具返回了空结果,不要只说"搜索完成",而要明确告诉模型"搜索返回了 0 条结果,可能需要换关键词或换数据源"。

1.7 安全层:不是可选项,是必选项

安全层在原型阶段经常被忽略,但一旦上线就是致命的。Agent 的安全问题比普通 LLM 应用更复杂,因为它能执行动作。

安全层要覆盖几个方面:输入过滤——防止恶意指令注入;工具权限控制——不是所有工具在任何场景下都能调用;输出审查——防止 Agent 生成或执行有害内容;操作审计——记录每一步动作,便于追溯。

我特别想强调的是工具权限的最小化原则。每个工具只给完成当前任务所需的最小权限,不要图省事给一个大权限工具。比如文件操作,读和写要分开,写操作要限定目录范围。这些在原型阶段可能觉得麻烦,但上线后能避免很多灾难性问题。

2. 七个决策点:工程实现中的关键分叉路口

七要素讲的是"系统由什么组成",七个决策点讲的是"每个环节你要做什么选择"。这些决策点没有标准答案,但有明显的优劣之分,选错了会在后期付出很大代价。

2.1 决策点一:单 Agent 还是多 Agent

这是架构层面的第一个分叉。单 Agent 是一个模型驱动所有工具和流程,多 Agent 是多个专职 Agent 协作完成一个任务。

单 Agent 的优势是简单、调试方便、状态管理集中。劣势是当任务复杂度上升时,一个模型的上下文和注意力会成为瓶颈。多 Agent 的优势是每个 Agent 可以专注自己的领域,用不同的模型和工具集,整体能力上限更高。劣势是通信成本高、状态同步复杂、调试困难。

我的判断标准是:如果任务可以清晰地分成几个独立子领域,且子领域之间的交互不频繁,就用多 Agent;否则先用单 Agent,遇到瓶颈再拆。很多项目一上来就搞多 Agent,结果大部分时间花在调试 Agent 之间的通信上,核心业务逻辑反而没做好。

如果决定用多 Agent,还要决定协作模式。常见的有主管模式(一个协调 Agent 分配任务给执行 Agent)、流水线模式(Agent 按顺序处理)、辩论模式(多个 Agent 对同一问题给出方案再择优)。主管模式最常用,也最容易控制。

2.2 决策点二:ReAct 还是 Plan-and-Execute

这是循环机制的核心选择。ReAct 是"推理-行动"交替进行,每一步都根据当前观察决定下一步。Plan-and-Execute 是先制定完整计划再执行。

ReAct 的优点是灵活、适应性强,适合环境不确定、需要频繁调整的场景。缺点是容易短视,可能做出局部最优但全局次优的决策。Plan-and-Execute 的优点是全局视野好、执行效率高,适合流程相对固定的场景。缺点是计划一旦制定就缺乏灵活性,遇到意外情况需要重新规划。

实际项目中,我更多用的是混合方案:外层用 Plan-and-Execute 做阶段划分,内层用 ReAct 处理每个阶段内的具体步骤。这样既有全局方向,又有局部灵活。纯 ReAct 适合探索性任务,纯 Plan-and-Execute 适合流程化任务,混合方案适合大多数实际业务场景。

还有一个细节:计划的可修改性。即使是 Plan-and-Execute,也要允许在执行过程中修改计划。我通常会在每个阶段结束后加一个"计划复审"步骤,让模型判断是否需要调整后续计划。

2.3 决策点三:工具调用的粒度怎么定

工具粒度是很容易被低估的决策点。粒度太粗,一个工具做太多事,模型难以精确控制;粒度太细,工具数量爆炸,模型选择困难。

我的经验法则是:一个工具只做一件事,但这件事要有完整的业务语义。比如"发送邮件"是一个合适的粒度,"连接 SMTP 服务器"和"构造邮件内容"和"发送"分成三个工具就太细了,"处理所有客户沟通"又太粗。

另一个考虑是参数复杂度。如果一个工具需要超过 5-6 个参数,通常说明它承担了太多职责,应该拆分。反过来,如果一个工具没有任何参数,可能它太简单了,可以直接内置到流程里而不必做成工具。

工具命名也很关键。名称要能自解释,让模型一看就知道什么时候用。我习惯用"动词+名词"的格式,比如search_documents、create_task、send_notification,避免用do_stuff这种模糊命名。

2.4 决策点四:状态存在哪里、怎么存

状态管理是 Agent 工程中最容易出问题的环节。状态存哪里、怎么序列化、怎么恢复,这些决策直接影响系统的可靠性和可调试性。

状态存储有三个层次的选择。内存状态最快但易失,适合单次会话内的临时状态。外部存储持久但慢,适合跨会话的长期状态。混合方案是热状态在内存、冷状态定期持久化,兼顾速度和可靠性。

我实际项目中用的是混合方案:当前执行状态放在内存对象里,每完成一个步骤就序列化一份快照到外部存储。这样即使进程崩溃,也能从最近的快照恢复,不会丢失全部进度。

状态的序列化格式也有讲究。JSON 最通用但体积大,MessagePack 或 Protobuf 更紧凑但可读性差。如果状态需要人工排查,JSON 的便利性通常值得那点体积代价。如果状态量很大且不需要人工看,可以用更紧凑的格式。

还有一个关键决策:状态是集中管理还是分散管理。集中管理是一个全局状态对象,所有组件读写同一份状态。分散管理是每个组件维护自己的状态,通过消息传递同步。集中管理简单但容易成为瓶颈,分散管理灵活但一致性难保证。我倾向于集中管理,因为 Agent 系统的状态一致性比性能更重要。

2.5 决策点五:失败重试的策略怎么设计

Agent 系统一定会遇到失败:工具超时、模型输出格式错误、外部服务不可用。失败重试策略设计得好不好,决定了系统是"偶尔出错但能自愈"还是"一错就崩"。

重试策略要分错误类型来设计。瞬时错误(网络抖动、临时限流)适合立即重试,通常重试 2-3 次就能成功。逻辑错误(参数不对、格式不符)不适合盲目重试,应该先修正再重试。永久错误(权限不足、资源不存在)重试多少次都没用,应该直接降级或上报。

重试的退避策略也很重要。固定间隔重试在对方服务过载时会加剧问题,指数退避(每次重试间隔翻倍)更合理。我通常用"指数退避 + 随机抖动",避免多个请求同时重试造成惊群。

还有一个容易被忽略的点:重试的上限和降级路径。重试不能无限进行,要有明确的上限。达到上限后要有降级方案,比如返回缓存结果、返回部分结果、或者明确告知用户当前无法完成。没有降级路径的重试就是在烧钱。

2.6 决策点六:上下文怎么组装和压缩

上下文组装是每轮循环都要做的事,但很多项目在这上面做得很粗糙,导致模型表现不稳定。

上下文组装的核心原则是:把最相关的信息放在最显眼的位置。模型对开头和结尾的信息注意力最高,中间部分容易被忽略。所以关键指令放开头,当前任务状态放结尾,参考信息放中间。

上下文压缩是长对话场景的必备能力。压缩策略有几种:滑动窗口是只保留最近 N 轮对话,简单但会丢失早期信息。摘要压缩是把早期对话总结成一段话,保留关键信息但会损失细节。检索压缩是把历史对话存起来,需要时检索相关片段注入,灵活但依赖检索质量。

我实际用的是摘要 + 检索的混合方案:近期对话保留原文,中期对话做摘要,远期对话存起来按需检索。这样在大多数场景下都能平衡信息完整性和上下文长度。

2.7 决策点七:怎么评估 Agent 的表现

没有评估就没有优化。Agent 的评估比普通 LLM 应用更复杂,因为它涉及多步骤、多工具、多轮交互。

评估要分过程指标和结果指标。过程指标看每一步的质量:工具选择准确率、参数正确率、循环效率(完成任务的步数)、失败恢复率。结果指标看最终产出:任务完成率、用户满意度、端到端延迟、成本。

我习惯建一个回归测试集,把典型任务和边界情况都收录进去,每次改动后跑一遍,看指标有没有退化。这个测试集不需要很大,几十个精心设计的用例就能覆盖大部分问题。关键是持续维护,每次发现新的失败案例就加进去。

评估的自动化程度也很重要。完全人工评估成本太高,完全自动评估又可能不准。我的做法是:用规则做初筛(格式对不对、有没有明显错误),用 LLM 做质量评分(相关性、完整性、逻辑性),人工只复核有争议的案例。

3. 循环机制:Agent 的心脏怎么跳

循环机制是 Agent 工程中最核心也最容易出问题的部分。这一章把循环的设计、实现和调优讲透。

3.1 一个最小可用的 Agent 循环长什么样

先看一个最简化的循环结构,用伪代码表示:

def agent_loop(user_input, max_iterations=10): state = init_state(user_input) for i in range(max_iterations): context = build_context(state) response = llm.invoke(context) action = parse_action(response) if action.type == "finish": return action.content if action.type == "tool_call": result = execute_tool(action.tool_name, action.params) state.add_observation(result) if no_progress(state, window=3): return fallback_response(state) return max_iterations_response(state)

这个循环包含了几个关键设计:最大迭代次数限制、完成判断、工具执行、无进展检测。看起来简单,但每个环节都有细节要处理。

build_context决定了模型看到什么,这是影响表现最大的环节。parse_action决定了模型输出怎么转成可执行动作,格式解析的鲁棒性直接影响系统稳定性。no_progress检测防止死循环,判断逻辑需要根据具体场景调整。

3.2 循环终止:怎么判断"真的完成了"

循环终止判断是 Agent 循环中最微妙的环节。判断太早,任务没完成就退出;判断太晚,浪费资源还可能出错。

我用的终止条件组合是这样的:

终止条件触发逻辑适用场景
模型显式完成模型输出 finish 动作正常完成
最大迭代次数达到预设上限防止无限循环
无进展检测连续 N 轮无有效动作防止原地打转
错误累积连续 N 次工具调用失败防止无效重试
超时总执行时间超限防止长时间占用

模型显式完成是最理想的终止方式,但不能完全信任。我遇到过模型在任务只完成一半时就输出"完成"的情况,所以通常还会加一个完成度校验:让模型在声明完成时同时输出一个完成度自评,低于阈值时触发一次"你确定完成了吗"的确认。

无进展检测的"进展"定义很关键。不能只看有没有工具调用,而要看状态有没有实质变化。比如连续三轮都在搜索同样的关键词,即使每轮都有工具调用,也是无进展。我的做法是给状态加一个哈希,每轮比较哈希是否变化,连续多轮不变就判定无进展。

3.3 循环中的错误恢复:从失败中继续而不是重来

Agent 执行过程中出错是常态,关键是怎么从错误中恢复而不是整个重来。

错误恢复的核心是状态快照 + 局部回滚。每完成一个成功的步骤就存一个快照,出错时回滚到最近的成功快照,然后尝试替代路径。这样不需要从头开始,节省时间和成本。

替代路径的生成有两种方式。一种是预定义备选:每个工具配一个或多个备选工具,主工具失败时自动尝试备选。另一种是动态生成:把错误信息反馈给模型,让模型决定怎么调整。我通常两者结合:有预定义备选时优先用备选,没有时让模型动态决策。

错误恢复还要考虑错误传播。一个步骤失败可能导致后续步骤都无法执行,这时候要判断是"局部失败"还是"全局失败"。局部失败可以绕过继续,全局失败需要重新规划。判断依据是当前步骤是否是后续步骤的前置依赖。

3.4 循环效率优化:怎么让 Agent 少走弯路

Agent 循环的效率直接影响成本和用户体验。同样一个任务,优化好的循环可能 5 步完成,没优化的可能 15 步还在打转。

效率优化的第一个抓手是减少无效工具调用。常见做法是在工具调用前加一层预判:根据当前状态判断这个工具调用是否可能有效,无效的直接跳过。比如已经知道某个数据源不可用,就不要再去调那个数据源的工具。

第二个抓手是并行化。如果多个工具调用之间没有依赖关系,可以并行执行。比如同时搜索多个数据源、同时查询多个 API。并行化能显著缩短总执行时间,但要注意并发控制和错误处理。

第三个抓手是缓存。相同或相似的查询结果可以缓存,避免重复调用。缓存的关键是键的设计——键太细命中率低,键太粗可能返回错误结果。我通常用"工具名 + 归一化后的参数"作为缓存键。

第四个抓手是提前终止。当已经收集到足够信息可以回答用户问题时,不必执行完所有计划步骤。这需要模型有能力判断"信息是否充分",我通常会在每步后加一个轻量的充分性检查。

4. 工具调用:Agent 的手脚怎么用

工具调用是 Agent 从"思考"到"行动"的桥梁。这一章把工具调用的工程细节讲清楚。

4.1 工具描述怎么写才能让模型选对

工具描述是模型选择工具的唯一依据,写得好不好直接决定选择准确率。

一个好的工具描述包含四个部分:功能说明(这个工具做什么)、使用场景(什么时候该用)、参数说明(每个参数的含义和格式)、返回说明(返回什么格式的数据)。

功能说明要具体,不要用模糊词汇。比如"处理文档"就不如"从 PDF 文件中提取文本内容"清晰。使用场景要写清楚边界,比如"当需要从非结构化文档中获取信息时使用,不适用于结构化数据库查询"。

参数说明要标注类型、是否必填、取值范围。对于枚举类型,把所有可能值列出来。对于字符串类型,说明格式要求(比如日期用 YYYY-MM-DD 格式)。

返回说明经常被忽略,但很重要。模型需要知道工具返回什么格式,才能正确解析和使用。如果返回可能为空,要明确说明空值的情况。

我踩过的一个坑是:工具描述写得太简略,模型经常在不适用的场景调用它,或者在适用场景忘了调用。后来把描述扩充到包含正例和反例,选择准确率明显提升。

4.2 工具参数校验:在模型和工具之间加一道防线

模型生成的工具参数不一定合法,直接传给工具可能导致各种问题。在中间加一道校验层是必要的。

校验分格式校验和语义校验。格式校验检查参数类型、必填项、取值范围是否符合 schema。语义校验检查参数在业务上是否合理,比如日期不能是过去的时间、ID 必须存在。

校验失败时的处理策略很重要。不能简单报错让模型重试,因为模型可能反复生成同样的错误参数。我的做法是:校验失败时,把具体的错误原因和修正建议一起返回给模型,引导它生成正确的参数。比如"参数 date 格式错误,应为 YYYY-MM-DD 格式,你提供的是 2024/01/01"。

对于高频错误,可以在校验层做自动修正。比如日期格式错误自动转换、字符串前后空格自动去除、枚举值大小写自动归一化。这样能减少一轮往返,提升效率。

4.3 工具执行的安全边界:什么能做什么不能做

工具执行的安全边界是 Agent 上线前的必答题。没有安全边界的 Agent 就是一个随时可能闯祸的不定时炸弹。

安全边界的设计原则是最小权限 + 显式授权 + 操作审计。最小权限是每个工具只给完成功能所需的最小权限。显式授权是敏感操作需要额外确认。操作审计是记录每一步操作便于追溯。

具体到实现,我会给每个工具打上风险等级标签:低风险(只读查询)、中风险(写入但可撤销)、高风险(不可逆操作)。低风险工具可以直接执行,中风险工具需要记录详细日志,高风险工具需要二次确认或人工审批。

还有一个容易忽略的点是工具的组合风险。单个工具可能都是安全的,但组合起来可能产生风险。比如"读取文件"和"发送邮件"单独都安全,但组合起来可能泄露敏感信息。所以安全边界不仅要看单个工具,还要看工具调用的序列模式。

4.4 工具返回结果的处理:从原始数据到模型可用的信息

工具返回的原始数据通常不能直接给模型用,需要经过处理。

处理包括格式转换、信息提取、长度控制。格式转换是把工具返回的格式转成模型容易理解的格式,比如把 JSON 转成自然语言描述。信息提取是从大量返回数据中提取关键信息,避免无关信息干扰模型。长度控制是限制返回信息的长度,超长时做截断或摘要。

我通常会在工具和模型之间加一个结果处理器,每个工具配一个处理器。处理器负责把原始返回转成"模型友好"的格式。这样模型看到的是经过整理的信息,而不是一堆原始数据。

结果处理还要考虑错误信息的处理。工具执行失败时,返回的错误信息要清晰、可操作。不要返回"Error 500"这种模型看不懂的信息,而要返回"服务暂时不可用,建议稍后重试或使用备选数据源"这种模型能据此决策的信息。

5. 状态管理与上下文工程

状态和上下文是 Agent 系统的"内存",管理得好不好直接影响系统的稳定性和能力上限。

5.1 状态对象的设计:结构化比什么都重要

状态对象的设计原则是结构化、可序列化、可版本化。结构化意味着状态有明确的字段和类型,不是一堆散乱的键值对。可序列化意味着状态能存能取,支持持久化和恢复。可版本化意味着状态结构变化时能兼容旧数据。

一个典型的状态对象包含这些字段:会话标识(区分不同会话)、任务描述(当前要完成什么)、执行历史(已经做了哪些步骤)、当前步骤(正在做什么)、中间结果(收集到的数据)、错误记录(遇到的失败)、元信息(时间戳、版本号等)。

状态更新要遵循单一写入原则:每个字段只有一个组件负责写入,其他组件只读。这样避免多组件同时写导致的状态不一致。如果确实需要多组件写,要用锁或事务来保证一致性。

状态的生命周期管理也很重要。会话结束后状态怎么处理?是保留一段时间还是立即清理?保留的话保留多久?这些要根据业务需求和数据敏感度来定。涉及敏感信息的状态要及时清理,普通状态可以保留一段时间用于分析和调试。

5.2 上下文窗口的分配策略

上下文窗口是有限资源,怎么分配直接决定模型能看到什么。

我的分配策略是固定比例 + 动态调整。固定比例是给各类信息分配基础配额,比如系统指令 10%、任务描述 15%、执行历史 30%、当前观察 25%、工具定义 20%。动态调整是根据实际情况在基础配额上浮动,比如工具多的时候工具定义占比上升,历史长的时候历史占比上升。

分配的核心原则是优先级排序。最不能丢的是系统指令和当前任务,其次是当前观察,再次是执行历史,最后是工具定义。当空间不够时,按这个优先级从低到高裁剪。

裁剪策略也有讲究。执行历史裁剪时,优先保留最近的和最关键的(比如出错的步骤),中间的成功步骤可以压缩成摘要。工具定义裁剪时,优先保留当前任务可能用到的工具,不相关的可以暂时移除。

5.3 长对话的压缩与检索

长对话场景下,上下文压缩是必须的。压缩的目标是在有限空间里保留最多有用信息。

压缩策略我分三级。一级压缩是去除冗余,比如重复的确认信息、格式化的空行、无关的客套话。二级压缩是摘要,把多轮对话总结成一段话,保留关键决策和结论。三级压缩是检索,把历史对话存到外部,需要时检索相关片段。

检索的质量取决于索引的设计。我通常用混合索引:关键词索引保证精确匹配,向量索引保证语义匹配。检索时两路都查,合并结果后按相关性排序。

压缩的触发时机也很关键。不能等到上下文满了才压缩,那样会导致突然的信息丢失。我通常在上下文使用率达到 70% 时开始预警,达到 85% 时触发压缩。这样有缓冲空间,不会因为压缩导致模型表现突然下降。

5.4 状态恢复:崩溃后怎么接着干

状态恢复是生产环境 Agent 的必备能力。没有状态恢复,一次崩溃就丢失全部进度。

恢复的基础是定期快照。每完成一个关键步骤就存一份状态快照,快照包含恢复所需的所有信息。快照的存储要可靠,通常用外部数据库而不是本地文件。

恢复的流程是:检测到崩溃 → 加载最近的快照 → 校验快照完整性 → 从快照点继续执行。校验很重要,因为快照可能损坏或不完整,直接用可能导致更严重的问题。

恢复还要考虑幂等性。从快照恢复后重新执行的步骤,可能之前已经执行过了。如果步骤不幂等(比如发送邮件),重复执行会造成问题。所以要么保证步骤幂等,要么在快照里记录已执行的步骤,恢复时跳过。

6. 从原型到生产:上线前必须过的几道关

原型能跑通不代表能上线。这一章讲从原型到生产要补的课。

6.1 并发场景下的 Agent 行为

单用户场景下跑得好好的 Agent,到了并发场景可能完全不是那么回事。

并发带来的第一个问题是资源竞争。多个 Agent 实例同时调用同一个工具或访问同一份状态,可能产生冲突。解决方式是资源隔离或加锁。资源隔离是每个实例用独立的资源,加锁是共享资源但串行访问。我倾向于资源隔离,因为加锁会降低并发度。

第二个问题是成本控制。并发上去后,LLM 调用成本可能指数级增长。需要设置全局配额和单用户配额,防止个别用户或异常情况导致成本失控。配额可以按调用次数、token 数或金额来设。

第三个问题是公平性。高并发时,某些请求可能被饿死。需要设计调度策略,保证每个请求都有机会被处理。简单的做法是队列 + 轮询,复杂的可以用优先级队列。

6.2 可观测性:怎么知道 Agent 在干什么

Agent 系统比普通应用更难调试,因为它的行为是模型驱动的,不完全可预测。可观测性是调试和优化的基础。

可观测性要覆盖三个层面:指标(Metrics)、日志(Logs)、追踪(Traces)。指标是聚合数据,比如任务完成率、平均步数、工具调用分布。日志是详细记录,每一步的输入输出都要记。追踪是跨步骤的关联,把一次任务的所有步骤串起来看。

我特别想强调追踪的重要性。Agent 的一次任务可能涉及几十次 LLM 调用和工具调用,没有追踪根本理不清。追踪要记录每一步的输入、输出、耗时、状态变化,最好能可视化展示。

日志的结构化也很重要。不要用纯文本日志,要用结构化格式(比如 JSON),方便查询和分析。关键字段包括时间戳、会话 ID、步骤序号、动作类型、输入摘要、输出摘要、耗时、错误信息。

6.3 成本控制:Agent 烧钱的地方在哪里

Agent 的成本比普通 LLM 应用高得多,因为一次任务可能调用几十次模型。成本控制是上线前必须解决的问题。

成本主要来自三块:模型调用、工具调用、存储。模型调用通常是大头,尤其是用大模型做主推理时。工具调用看具体工具,有些外部 API 按次收费。存储主要是状态和日志的存储成本。

模型调用的优化有几个方向。模型分级是简单任务用轻量模型,复杂任务用大模型。缓存是相同或相似的请求复用结果。批处理是把多个小请求合并成一个大请求。提前终止是信息足够时不再继续调用。

我实际项目中用得最多的是模型分级 + 缓存。模型分级能省 30-50% 的成本,缓存能省 20-40%。两者结合,整体成本能降到原来的三分之一左右。

6.4 灰度发布与回滚

Agent 系统的行为不完全可预测,直接全量上线风险很大。灰度发布是降低风险的有效手段。

灰度发布的策略是:先小流量验证,逐步扩大流量,同时监控关键指标。指标正常就继续扩大,指标异常就暂停或回滚。

回滚能力是灰度发布的前提。回滚要快、要干净。快是指发现问题后能立即切回旧版本。干净是指回滚后不留下脏数据或中间状态。我通常用版本化部署 + 流量切换来实现快速回滚,新旧版本同时运行,通过流量比例控制。

灰度期间要重点监控的指标包括:任务完成率、平均步数、错误率、延迟、成本。任何一个指标明显退化都要警惕。

7. 几个实际项目中的经验教训

最后分享几个我在实际项目中踩过的坑和总结的经验,这些是文档里不会写的。

7.1 不要过早优化循环步数

刚开始做 Agent 时,我总想着怎么让循环步数最少。后来发现,步数少不一定好。有些任务需要多步探索才能做对,强行压缩步数会导致质量下降。

正确的做法是先保证质量,再优化效率。先让 Agent 能稳定完成任务,哪怕步数多。然后再分析哪些步骤是冗余的,有针对性地优化。优化的目标是"消除无效步骤",而不是"减少所有步骤"。

7.2 工具不是越多越好

工具数量增加会带来两个问题:模型选择困难、维护成本上升。我见过一个项目有 50 多个工具,模型选择准确率不到 60%。

我的建议是工具数量控制在 15 个以内,超过就考虑分组或合并。分组是把工具按领域分成几组,模型先选组再选工具。合并是把功能相近的工具合并成一个,通过参数区分具体行为。

7.3 状态设计要留扩展余地

状态对象一旦上线就很难改,因为改了要兼容旧数据。所以设计时要留足扩展余地。

我的做法是:核心字段用强类型,扩展字段用元数据字典。核心字段是必须的、稳定的,元数据字典是灵活的、可扩展的。这样新增信息时可以放元数据字典,不用改核心结构。

7.4 评估要趁早做

很多项目到快上线才想起来做评估,这时候发现问题已经很难改了。评估应该从项目第一天就开始。

早期评估不需要很复杂,几个典型用例 + 人工检查就够了。随着项目推进,逐步扩充用例、增加自动化检查。到上线时,评估体系已经比较完善了。

7.5 人工兜底不是失败

有些团队觉得 Agent 需要人工兜底是能力不足的表现,想尽办法追求全自动。我的看法是:人工兜底是负责任的设计,不是失败。

Agent 再强也有边界,遇到边界情况时人工介入是合理的。关键是设计好交接机制:什么时候触发人工、交接时传递哪些信息、人工处理后怎么回到自动流程。这些设计好了,人机协作的效率比纯自动或纯人工都高。

我在实际项目中的体会是,Agent 工程最难的不是某个技术点,而是整体的系统设计和权衡。七要素和七个决策点提供了一个思考框架,但具体怎么选还要结合业务场景、团队能力和资源约束。没有银弹,只有适合当前情况的方案。

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

RISC-V裸机启动全流程:从复位向量到main函数的七步实现

1. 这不是“Hello World”,而是芯片睁眼的第一瞥:RISC-V bare-metal 启动到底在干啥?你手头那块刚焊好的 RISC-V 开发板,通电后 LED 不亮、串口没输出、调试器连不上——它不是坏了,它只是还没“醒”。而唤醒它的过程&…

作者头像 李华
网站建设 2026/10/8 23:56:04

企业自建Docker镜像服务:从Harbor落地到高可用运维实践

去年我们容器化项目刚上线那会儿,运维同事半夜给我打电话:一批新节点同时从公共仓库拉同一个基础镜像,拉了一个多小时还没完,有一半节点直接报连接超时。那晚之后,我意识到“企业内自搭建容器镜像服务”这件事&#xf…

作者头像 李华
网站建设 2026/10/8 23:55:54

从文献堆到研究地图:AI综述将走向哪里

过去,文献综述常被形容为“把读过的文章写出来”。但真正动笔后,很多研究者才会发现:难点并不只是阅读数量,而是如何从分散的资料中提炼出研究脉络,判断不同观点之间的关系,并进一步找到值得讨论的问题。从…

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

2026降AI率工具实测,专科生论文必看推荐

专科毕业论文的AI检测越来越严,不少院校已把AIGC检测纳入审核流程。降AI率成了专科生答辩前的硬仗,工具选不对,改到天亮也白搭。这篇把市面上8款降AI率工具逐一实测,说说哪些真能解决问题,哪些只是表面功夫。 专科论文…

作者头像 李华
网站建设 2026/10/8 23:51:34

XXL-JOB 容器化部署实战:K8S 集群 YAML 配置与避坑指南

简介:这份资源面向需要在 Kubernetes 集群中落地 XXLJOB 的运维与后端开发人员,提供一份经过实际部署验证的 YAML 清单,解决容器化环境下任务调度平台快速搭建与配置落地的问题。压缩包内共 1 个文件,为单个 yaml 类型清单&#x…

作者头像 李华
网站建设 2026/10/8 23:49:05

HTML5 Input类型全解析:表单校验、移动端适配与兼容性实战

最近在做一个后台管理系统改造,表单这块让我花了不少时间。项目里既有老的登录注册页,也有新增的数据报表筛选区,各种输入需求混在一起,HTML5 新增的 Input 类型确实帮了大忙,但用不好也会给你挖坑。我从 HTML5 刚普及…

作者头像 李华