news 2026/10/31 15:49:39

AI Agent工程实现:七要素拆解与七个关键决策点指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Agent工程实现:七要素拆解与七个关键决策点指南

写 Agent 的工程实现,最怕的就是“看了很多概念,一动手就懵”。网上讲 AI Agent 的文章要么堆术语,要么只给 demo,真正能指导你把一个 Agent 从想法推到可运行状态的很少。这篇文章我打算换个思路,不聊虚的,把 Agent 拆成两半来看:一半是它运行所需要的七要素,一半是你在工程里必须拍板的七个决策点。七要素回答“一个 Agent 由什么构成”,七个决策点回答“你该怎么把它做出来”。七要素是解剖学,七个决策点是施工图,两套东西合起来,才是完整的工程视角。

这篇文章适合两类人:一是准备在项目里引入 Agent、但还在犹豫架构怎么搭的开发者,二是已经跑过简单的 Agent demo、想搞清楚下一步该往哪使劲的人。我会把每个要素和每个决策点背后的为什么讲清楚——为什么这么选、不这么做会踩什么坑、换一种方案代价是什么。最后给一个最小可跑的工程样例和一份排查清单,你照着改就能用。

在动手之前,先搞清楚 Agent 到底在解决什么问题

很多团队掉进一个坑:把 Agent 当成普通的 API 封装,以为就是一个大模型加几个提示词。结果做出来东西能聊天,干不了活。想理解 Agent 的工程实现,先得理解它和你以前写的软件到底有什么不一样。

1.1 从“聊天窗口”到“能干活的人”

传统软件是确定性的:你写一个函数,传参,它返回结果,逻辑分支是写死的。LLM 应用是概率性的:你给一段提示词,它生成一段文字,结果有一定的不可预测性。而 Agent 处在两者的交叉点上——它要用概率性的模型,去执行确定性目标,比如“帮我把这周的用户反馈整理成表格”“定时检查服务器日志并给出告警”。

这意味着 Agent 的代码逻辑不是从输入到输出的一条直线,而是一个循环:感知当前状态,决定下一步做什么,调用工具,观察结果,再决定下一步。很多人把 Agent 理解成“带工具的大模型”,这是不够的。带工具只是让它能行动,真正的 Agent 要有“目标—计划—行动—观察—调整”的闭环。你可以类比成带实习生:你不能只给他一份文档让他汇报工作,你得给他目标、给他人脉和工具,还得容忍他中间走错路再自己绕回来。

工程上这种循环的通用名称叫 Agent Loop,核心就是 ReAct 模式(Reason + Act)的变体。它的基本结构是:

  1. 模型收到用户请求,先推理(Reason),判断当前需要什么信息、应该走哪条路径。
  2. 模型输出一个动作(Act),往往是调用某个函数,比如搜索、查数据库、发请求。
  3. 系统执行动作,把结果喂回给模型。
  4. 模型基于新信息继续推理,直到任务完成。

这里有一个大家容易忽略的点:模型在哪一步停止,怎么判断任务完成,通常不靠模型自觉,而是靠工程上的终止条件。这一点后面在决策点部分会专门展开。先记住结论——Agent 的本质是一个带反馈闭环的任务执行系统,不是单次生成。

1.2 Agent 跟传统软件差的不是功能,是“控制流”

传统程序里,控制流是你写死的:if 分支、for 循环、函数调用,都在代码里。Agent 里,控制流变成了模型根据上下文动态生成的决策。代码不再决定每一步做什么,只决定“每一步可能有哪些选项、什么情况下可以做什么、做了之后如何反馈”。这对程序员是一个很大的心智转变。

举个直观的例子。你想写一个自动处理客户邮件并按紧急程度分类的程序。传统做法是:先设规则(标题含“投诉”且正文含“退款”则标为高优),再写一堆正则,维护起来很痛苦,规则永远追不上语言的多样性。Agent 的做法是:给模型一个“标记紧急程度”的工具,让它自己读邮件、判断紧急程度、调用工具打标签,甚至写一段回复草稿。规则没有变少,而是从“预先穷举”变成“动态判断”,规则变成了工具的边界、模型的约束,而不是逻辑本身。

由此引出 Agent 工程实现的第一个基本矛盾:自由度和可控性。Agent 自由度越高,越能处理复杂任务,但越难控制、越容易出错。自由度太低,又退化成规则系统,失去 Agent 的意义。整个工程实现的过程,说白了就是在画一条边界:在边界之内让模型自由发挥,在边界之外用代码兜底。七要素里的“安全与约束”和七个决策点里的“终止条件与降级策略”,都是在处理这一件事。

1.3 这套思路能帮你省下什么

把七要素和七个决策点吃透,最大的收益不是能写出一个惊艳的 demo,而是避开几个大坑。

第一个坑是架构冒进。一上来就上多 Agent 编排、搞复杂的记忆系统,结果问题本身用一个函数调用就能解决,白白引入大量延迟和不确定性。理解了七要素,你会知道记忆、规划、编排各自解决什么问题,按需裁剪。

第二个坑是评测缺失。很多团队把 Agent 接入生产之后,出了 bug 不知道该修模型、修提示词还是修改器,因为没有一套系统的评测集和回归测试。七个决策点里专门有评测与迭代这一环,我会给一套低成本可落地的评测方案。

第三个坑是成本失控。Agent 是一个会循环调用模型的系统,一次任务可能消耗几十万 tokens,如果不对工具调用次数、上下文长度、模型规格做约束,账单会教你重新做人。这个在部署决策点里详细说。

解构七要素:一台能跑起来的 Agent,身上必须有这几块骨头

七要素是我从工程视角抓出来的、一个 Agent 系统必备的七个组成部分。跟你可能见过的其他分类法略有不同,这套更偏“运行依赖”而不是“学术概念”,每个要素对应一个明确的工程模块。

2.1 七要素全景速览

先给一张总表,把七个要素、它解决的问题、以及对应的工程模块列清楚。后面逐个拆解。

要素解决什么问题对应工程模块
大模型底座理解和生成的自然语言能力模型 API / 本地部署
任务规划器决定下一步做什么提示词策略、规划器组件
记忆系统保存历史信息与长期知识会话缓存、向量数据库、KV存储
工具集与外部世界交互的接口Function Calling、工具注册中心
编排框架组织上述模块的循环Agent Loop、状态机、框架(LangGraph等)
反馈与反思机制从失败或结果中改进Evaluator、Reflection Prompt、自我修正
安全与约束限制行为边界与控制风险权限控制、输入输出过滤、熔断降级

这张表你要竖着看:大模型是底座,但光有它什么都做不了;规划、记忆、工具是三个支柱,分别解决“想”“记”“做”;编排是骨架,把它们串起来;反馈和安全是两个护城河,前者保证越跑越好,后者保证不跑偏。

在工程里这七个要素并不总是独立模块。比如规划器和反馈机制,很多时候就是几个提示词的区别;工具集和记忆系统往往要共享同一个底层存储。但拆开想是必要的,因为每个要素都有自己独立的故障模式。下面逐个讲它们的原理、陷阱和最少实现方式。

2.2 逐一拆解七个要素

大模型底座。这是最容易选、也最容易选错的要素。容易选是因为选择多:GPT、Claude、通义千问、GLM、Llama、Qwen,开源闭源一大堆。容易选错是因为很多人只看跑分和价格,忽略了两个关键维度。

第一是“工具调用能力”。Agent 系统高度依赖模型在结构化输出上的稳定程度——模型能不能稳定输出符合 schema 的 JSON,能不能在上下文很长之后仍然按照指令返回,而不是开始胡编。这类能力在普通榜单上看不出来,必须自己拿任务样例实测。第二是“上下文窗口的实际可用长度”。标称 128K 的模型,往往在超过 50K 之后表现明显下降、思维开始跳跃。你在选型时一定要记住:标称值和实际值之间有差距,Agent 场景必须压测。

任务规划器。规划是 Agent 和“AI 搜索”“聊天助手”的分水岭。它的职责是把一个模糊的指令拆成具体的子目标序列。工程实现有三种主流方案,复杂度和效果递增:

第一种是 ReAct 风格,即边做边想。模型每一步输出“thought—action—observation”,动态决定下一步,适合开放任务,但 token 消耗大、每一步都有出错风险。

第二种是 Plan-then-Execute,先让模型生成一份完整计划,再按计划执行,甚至计划可以单独用一个模型生成。优点是可控性强、每一步有据可依,缺点是计划可能一开始就错了,而且模型不会中途轻易调整。

第三种是混合式,比如 ReAct 循环 + 定期重规划。执行过程中,如果检测到连续 N 步没有进展,触发一次重规划。这种方式实现成本高一点,但稳定性最好,适合长期任务。

我的经验是:刚起步不要实现第三种,先用 ReAct 跑通,遇到规划质量问题了再升级。后面决策点部分我会讲怎么判断到底该不该升级。

记忆系统。记忆是 Agent 被低估的组件。很多初版 Agent 不做记忆,每次任务都是“失忆开局”,导致同样的问题反复错。记忆至少分两层来设计。

短期记忆对应会话内的上下文,就是你现在 Prompt 里塞的那些对话记录。工程上要管的是上下文长度:不控制的话,几轮对话就能把窗口撑爆,所以要有截断、摘要、滑动窗口机制。

长期记忆是跨会话的持久信息。最好的形态是“向量检索 + 结构化存储”组合:向量库存语义相似的历史,KV 或关系库存明确事实(比如用户的偏好设置)。工程上注意一个矛盾:不是所有信息都值得入库。存得越多,检索噪声越大。经验法则是:能直接从对话历史拿到的信息不要入长期记忆,频繁被查询的事实优先入,记忆写入要有准入条件。

工具集。工具是 Agent 的四肢,决定了它能做什么。工程实现核心是 Function Calling 这一套协议。所谓 Function Calling,本质上是让模型输出一个结构化的“工具调用请求”,而不是自由文本。你做这件事的时候就干三步:

  1. 把工具定义成 JSON Schema,包括名称、描述、参数结构。描述要写清楚什么时候用这个工具、参数格式是什么,因为模型是靠描述来选择工具的。
  2. 系统接收模型返回的工具调用请求,做参数校验,然后执行真实函数的调用。
  3. 把执行结果返回给模型,让其继续推理。

这里面九成的问题出在工具描述写得不清楚,或者参数校验没做——模型返回了一个不合法的参数,你没拦住,还直接发给后端,导致各种脏数据。后面排查清单里我会给具体症状和修法。

编排框架。编排负责把前四者串成循环。你可以自己写死循环,也可以选框架。自己写的自由度高,但状态管理容易乱;框架省事,但引入抽象和限制。

目前主流的选择是 LangGraph:它把 Agent Loop 显式建模成图结构,节点是“推理”“调用工具”“用户交互”,边是条件转移。比 LangChain 早期的 Chain 模型更贴合 Agent 场景,也更好控制。没有历史包袱的新项目,建议直接上 LangGraph 而不是 LangChain。LlamaIndex 在处理“文档 + 知识库”类的 Agent 时更顺手,如果你的 Agent 主要任务就是 RAG,优先考虑它。如果项目对性能要求高、又不想引入 Python 生态依赖,Rust 生态里也有不错的选择(比如 rig、genkit 这类库),只是生态成熟度比 Python 还是有差距,选它之前先确认手册和社区资源能满足你的问题排查需求。

反馈与反思机制。Agent 不可能一次做对,所以必须要有一套机制把“做错”变成“做对”。两层设计:

第一层是执行中的自我修正。模型调用工具得到结果后,发现结果不对,可以再试一次或换一个工具。工程上你要给这种“重试”留出次数上限,防止模型在同一问题上无限循环。第二层是执行后的反思。一次任务结束后,让模型写一段反思:哪里做得不好、为什么、下次怎么做。反思结果可以作为记忆写回长期存储,下次类似任务直接调用。

反思不是玄学,本质上是“让模型基于结果做一次归因分析”。归因分析的质量取决于你喂给它的信息是否完整。所以工程上要保证日志记录了完整的轨迹(thought、action、observation、final answer),反思 prompt 才能拿到原材料。

安全与约束。这项最后讲,但优先级最高。Agent 的安全性分三个层面:

第一层是权限控制。Agent 调用的每个工具,都要按最小权限原则授权。能让它只读的,不要给它写权限;能给它试运行环境的,不要直接上生产。很多人直接给 Agent 配了数据库管理员权限,一个错误的 SQL 就把表删了。第二层是内容安全。模型的输入输出要有过滤和审查机制,防止提示词注入——让外部输入(比如网页内容、用户消息)变成“指令”劫持 Agent。第三层是熔断降级。设置调用次数上限、异常重试上限、危险操作确认机制。比如 Agent 连续调用工具失败 5 次之后,不要继续尝试,应当把控制权交还给人。

到这里七要素就拆完了。你会发现它们之间不是孤立的:模型能力影响规划上限,规划结果决定工具调用,工具结果写入记忆,记忆又反过来影响下一次规划,编排把所有环节串成循环,反馈和安全保证循环可靠。七要素是横向的解剖结构,下面七个决策点是纵向的施工选择。

七个决策点:做 Agent 时真正要拍板的那些事

如果说七要素是“必须有哪些零件”,七个决策点就是“每个零件你打算怎么做”。决策点不分先后对错,只看场景适配。我按从“买什么模型”到“怎么上线运维”的顺序来讲,你可以照着这个顺序做一次选型评估。

3.1 决策点一:模型选型——不要只看跑分,要压测工具调用能力

模型选型是整个 Agent 的基石,选错了后面全都白搭。原则就一条:拿你的真实任务去做压测,别拿跑分当唯一指标。

具体操作建议:准备一个 20 到 30 条的“黄金评测集”,里面覆盖你 Agent 最典型的任务类型。比如你的 Agent 要查库存、生成订单,评测集就包含“不同表述但相同意图”的查询语句,以及几组容易混淆的边界情况。然后用候选模型各跑一轮,重点看三项指标:

一是工具调用格式的规范率。模型返回的 tool call 是不是总能符合 JSON Schema,有没有多余的字段、缺失参数、JSON 格式错误。二是边界情况的处理能力。面对含糊的用户指令,模型是主动追问,还是自己瞎猜。三是长上下文表现。把上下文逐步拉长到 50K 以上,看推理质量有没有肉眼可见的崩塌。

关于是否用本地模型:除非你有数据不出内网之类的合规要求,否则初期直接商用 API,开发效率高一个量级。私有化部署的拐点在“调用量稳定且足够大”之后,那时候用 vLLM 之类的推理框架跑开源模型,单位成本才划算。

3.2 决策点二:规划策略——用 ReAct 保底,按需升级

规划策略本质上是在“效率”和“确定性”之间权衡。我建议的路径是:默认 ReAct,遇到特定瓶颈再升级。

具体来说,出现以下三种情况之一,就考虑从纯 ReAct 升级到 Plan-then-Execute 或混合式:

  1. 任务链条很长(超过 5 个子步骤),ReAct 的轨迹太长,容易在中途跑偏。换成先出计划再执行,至少可以在第一步拦住明显错误的计划。
  2. 任务的每一步之间依赖关系明确,比如“先查汇率,再算总价,最后下单”。这种流程适合预定义 Plan,让模型按部就班走,减少自由度。
  3. 排查问题时发现模型在同一个错误上来回绕,说明它缺少对全局的把握,升级为重规划机制,每 N 步检查一次进度,卡住了就强制换策略。

对应地,如果你的任务只有两三步、用户意图相对明确,就别加复杂规划器了,ReAct 的简单循环完全够用。这里有一个很实用的原则:控制流的复杂度应该跟任务复杂度匹配,而不是跟技术潮流匹配。

3.3 决策点三:记忆设计——先分清“该记的”和“该忘的”

记忆设计最容易犯的错是“过度设计”。一上来就上向量数据库、加实体图谱,结果数据根本没积累起来,白白增加系统复杂度。我的建议是分三个层级递进,每个层级都有明确的触发条件。

第一层是会话内滑动窗口 + 摘要。这是所有 Agent 的标配。只保留最近几轮对话原文,更早的内容用模型摘要成一段话放在上下文最前面。这个层级的核心参数是窗口大小,经验值 10 到 20 轮,再结合模型上下文窗口动态调整。

第二层是工作记忆:把当前任务进行到一半的状态(比如“已查过库存,待确认价格”)存进一个结构化对象里。这种记忆不需要向量库,一个 JSON 对象就够。工作记忆要保证在每次模型推理时都能“看到”,因为它是任务推进的骨架。

第三层才是长期记忆,用向量库存事实性内容。这里要定好写入规则和检索规则。写入规则要有准入条件:这条信息是否会在未来的任务中被再次需要?含混不清的不要写。检索规则要限 top-k,比如取最相似的 5 条,宁可少取也不要让噪声干扰模型判断。

有一个容易忽略的工程细节:所有记忆操作都要跟业务数据隔离。Agent 的长期记忆存的是“辅助决策信息”,不是业务系统的权威数据。如果你让 Agent 把用户订单写进自己的记忆库里,等待你的将是数据一致性的噩梦。权威数据留在业务库里,Agent 的记忆只做缓存和索引。

3.4 决策点四:工具接入——工具描述写得好不好,直接决定 Agent 的上限

工具接入是 Agent 工程里性价比最高的一环:同一个模型,工具设计得好,任务完成率可以从 60% 提到 90%。而工具设计的功夫,九成花在写描述上。

每个工具的描述要回答三个问题:这个工具是干什么的?什么时候该用、什么时候不该用?参数分别代表什么、有什么格式要求?千万不要写得像 API 文档一样干巴巴全是字段名,要把使用场景写出来。举例说明:

一个“查询天气”的工具,差的描述是“根据城市名查天气”,好的描述是“当用户询问某个城市的天气情况时调用。城市名必须是中文,如‘北京’。若用户只提供日期未提供城市,需要先追问城市名再调用”。

注意最后一句,这其实是把“对话策略”写进了工具描述里,相当于给模型打了补丁。

另外,工具数量不是越多越好。模型在数十个工具之间做选择时,准确率会明显下降。经验上限是 10 到 15 个工具。超过之后,建议做工具分组,或者把多个相关操作合成一个工具,用参数区分动作。

参数的强校验也务必加上。模型输出参数偶尔会漏字段、类型错误,你要在调用真实函数之前做一次 schema 校验,不合法就打回让模型重新生成。这一步不是可选项,生产环境必须有。

3.5 决策点五:单 Agent 还是多 Agent——别为了“高级”而上多角色

多 Agent 现在是热门话题,但它不是银弹。我的建议很直接:单 Agent 能解决的问题,永远不要用多 Agent。多 Agent 的引入,至少要多付三倍以上的 token 成本、多管理几倍的失败模式,还要处理 Agent 之间的上下文隔离和信息传递。

什么场景真的需要多 Agent?三条判断标准:

  1. 任务里存在天然的角色边界,比如“研究助手”和“写作助手”,它们各自需要不同的系统提示词、不同的工具集,混在一起会让模型频繁切换上下文、表现下降。
  2. 单个 Agent 的上下文窗口装不下所有需要的背景信息,用多个 Agent 各管一段可以有效切分上下文。
  3. 子任务必须并行执行,比如同时查多路数据源,单 Agent 串行会太慢。

即使满足其中一条,你也要优先考虑“逻辑上的拆分”而不是“物理上的多 Agent 进程”。比如你还是用一个模型,但通过系统的状态机去切不同的提示词和工具集,这就是一个逻辑多 Agent 的实现。这种方案成本低得多,只是领域内的“一个 Agent”,工程上可控性更好。

如果你最终决定上多 Agent,务必要有主控 Agent(或者一个编排器)来统筹任务分发和结果汇总,不要让 Agent 之间直接协商。没有主控的 Agent 群聊,看着热闹,实际跑起来就是一场事故,根本收不了场。

3.6 决策点六:评测与回归——没有评测集的 Agent,就是一辆没刹车的车

评测是 Agent 工程里最容易被跳过的环节,但它是上线前的最后一道闸门。Agent 的评测跟传统 LLM 评测不一样:你不仅要测“最终答案对不对”,还要测“过程对不对”——工具调了几次、有没有浪费时间在无关调用上、有没有走向危险的路径。

低成本可落地的评测方案有三层:

第一层是最终答案质量。传统办法,可以人工打分或者用更强的模型做裁判。这层只看结果,实现简单,能拦下大部分明显错误。第二层是过程正确性。检查执行轨迹里的每一步:工具调用是否合理、参数是否正确、步骤顺序是否恰当。建议做成规则校验,比如“凡是调用支付工具前没有查余额的都算失败”。这层能抓到结果对但过程危险的情况。第三层是回归测试集。每次改提示词、改工具定义、换模型,都要跑一遍同一套测试集,对比通过率和轨迹差异,防止“修好一个 bug、引出三个新 bug”。

评测集不是为了上线前跑一次,而是为了上线后每一次迭代都跑。把它纳入你的 CI,Agent 变更自动触发回归。没有这套机制,后续优化基本靠感觉,踩坑是迟早的事。

3.7 决策点七:部署与成本——把 Agent 当服务来设计,而不是当脚本

Agent 上线和普通 API 服务有很多不同,最大的差异在于“执行时长”。一次 Agent 任务可能耗时几十秒甚至几分钟,所以把它包装成同步 HTTP 接口等着返回,体验会很差。更合理的形态是任务化:提交一个任务,返回任务 ID,前端轮询或者后端起 WebSocket 通知结果。

成本控制是部署环节的重头戏。Agent 的 token 消耗大头在两部分:一是循环过程本身,二是塞进上下文的记忆和工具结果。控制方法有四个:

  1. 限制最大迭代步数,比如撑死 15 步,到了没完成就强制结束,防止模型在死循环里烧 token。
  2. 对工具返回结果做截断。数据库查回来 1000 行,只拿前 20 行给模型看,其余存起来按需再查。这个措施能省下大量 token。
  3. 启用语义缓存。相同或相似的用户请求,直接复用之前的 Agent 执行结果或中间步骤结果,不要重新跑。在一个用户问题高度重复的业务里,缓存能省 30% 以上调用量。
  4. 分级用模型。规划用便宜的小模型,关键推理和工具选择用贵的大模型。这一步能显著降低成本,但对架构复杂度有要求,建议第一个版本先统一大模型,稳定后再优化。

部署运维上,还要把每一次 Agent 运行的全链路轨迹记录成结构化日志。这些日志既是排查问题的依据,也是后续优化评测集的素材。日志字段要包含:任务 ID、输入、每一步的 thought、action、observation、中间 token 数、耗时、最终结果、错误信息。日志记录得越好,后面迭代越快。

最小可用的 Agent 工程样例:从代码理解整套体系

前面讲了这么多,落到代码上才有体感。下面给一个最小但五脏俱全的 Agent 实现方案,基于 Python + LangGraph,核心功能是“天气查询 + 备忘录用例”,你可以在此基础上扩展自己的工具集。

4.1 工程结构与依赖准备

工程结构建议如下:

agent_project/ ├── main.py # 入口函数 ├── agent/ │ ├── graph.py # LangGraph 图定义 │ ├── tools.py # 工具函数注册 │ ├── state.py # 状态定义 │ └── prompts.py # 提示词管理 ├── tests/ │ └── eval_set.json # 评测集 └── pyproject.toml

依赖安装,核心就三个库:

pip install langgraph langchain-openai python-dotenv

我这里用 langgraph 作为编排框架,因为它把“节点 + 条件边”这套 Agent Loop 逻辑表达得最直观。需要说明的是,各家的工具定义接口会随版本变化,但总体思路一致:把工具注册给框架,框架负责把工具描述传给模型、把模型生成的工具调用翻译成真实函数执行。

4.2 核心实现:状态、工具、图

Agent 的状态用 TypedDict 定义。状态会在每个节点之间传递,相当于“工作记忆”的载体。这里把 messages 和 remaining_steps 放进了状态里,前者记录会话历史,后者记录剩余迭代步数。

from typing import Annotated, TypedDict class AgentState(TypedDict): messages: Annotated[list, "accepted_messages"] remaining_steps: int

工具函数是 Agent 的四肢。每个工具用装饰器注册,框架会根据函数签名和 docstring 自动生成 JSON Schema。值得注意的是,docstring 就是“工具描述”,你要把使用场景、参数格式、何时调用写清楚,这直接决定模型能不能调用对。

import json from langchain_core.tools import tool import httpx @tool def get_weather(city: str) -> str: """查询指定城市的当前天气。 适用于用户询问天气的场景。城市参数必须是中文城市名,例如“北京”。 如果用户没有给出城市名或给了英文城市名,先向用户追问或转换为中文后再调用。 """ # 实际项目里替换成真实天气 API mock_data = { "北京": {"temp": 18, "condition": "晴"}, "上海": {"temp": 22, "condition": "多云"}, } data = mock_data.get(city, {"temp": "unknown", "condition": "unknown"}) return json.dumps({"city": city, **data}, ensure_ascii=False) @tool def save_note(content: str) -> str: """保存一条备忘录。 当用户明确说“记住”“记一下”“备忘”等指令时调用。 content 参数是用户想保存的完整文字内容。 """ with open("notes.txt", "a", encoding="utf-8") as f: f.write(content + "\n") return "已保存"

图是编排的核心。这里的关键代码是 define_agent_graph 函数:它创建了一个 agent 节点(模型推理)、一个 tools 节点(执行工具调用),并在 tools 之后判断“是否还有步骤剩余”来决定是回到 agent 还是退出到 END。模型节点和工具节点交替执行,就是一个标准的 Agent Loop。

from langgraph.graph import StateGraph, END from langchain_openai import ChatOpenAI def create_agent_graph(): llm = ChatOpenAI(model="gpt-4o-mini") tools = [get_weather, save_note] llm_with_tools = llm.bind_tools(tools) def agent_node(state: AgentState): messages = state["messages"] # 把剩余步数告知模型,防止它无限循环 remaining = state.get("remaining_steps", 10) instruction = f"注意:你最多还有 {remaining} 步完成用户请求。" response = llm_with_tools.invoke(messages + [{"role": "system", "content": instruction}]) return {"messages": messages + [response], "remaining_steps": remaining - 1} def tools_node(state: AgentState): last_message = state["messages"][-1] # 遍历模型返回的工具调用请求,逐个执行 tool_results = [] for tool_call in last_message.tool_calls: tool_name = tool_call["name"] tool_args = tool_call["args"] matched_tool = next(t for t in tools if t.name == tool_name) result = matched_tool.invoke(tool_args) tool_results.append({ "role": "tool", "tool_call_id": tool_call["id"], "content": str(result), }) return {"messages": state["messages"] + tool_results} def should_continue(state: AgentState): last_message = state["messages"][-1] # 模型没有要求调用工具,说明任务结束了 if not last_message.tool_calls: return END # 步数耗尽,强制结束 if state.get("remaining_steps", 0) <= 0: return END return "tools" graph = StateGraph(AgentState) graph.add_node("agent", agent_node) graph.add_node("tools", tools_node) graph.set_entry_point("agent") graph.add_conditional_edges("agent", should_continue, {"tools": "tools", END: END}) graph.add_edge("tools", "agent") return graph.compile()

主入口负责接受用户输入、初始化状态并运行图。这里的一个细节是:用户消息被封装成“user”角色的 message,进入 agent 节点后,模型才能感知到任务目标。

def main(): graph = create_agent_graph() print("Agent 已启动,输入问题(输入 exit 退出)") while True: user_input = input(">> ") if user_input.strip().lower() == "exit": break result = graph.invoke({ "messages": [{"role": "user", "content": user_input}], "remaining_steps": 8, }) final_answer = result["messages"][-1].content print("Agent:", final_answer) if __name__ == "__main__": main()

4.3 跑通后的三个优化方向

这个最小实现跑通之后,你有三个优先级很高的优化方向。

第一个是把记忆加进来。现在的实现里,每次 invoke 都是独立的,线程退出就丢了上下文。你可以把 messages 持久化到 Redis 或者 SQLite,下次启动时读回最近几轮,再让模型把更早的内容做摘要。这对应七要素里的记忆系统。

第二个是给工具参数加强校验。现在模型返回非法参数时,代码会直接抛异常中止循环。你应该在 tools_node 里先做 JSON Schema 校验,不合法就让模型重试。实际生产里,这一步能减少至少三成的诡异故障。

第三个是加评测集。建一个 tests/eval_set.json,里面放十条用户指令和期望的工具调用序列,每次改完提示词就跑一遍,确保没有破坏已有能力。

常见问题与排查技巧实录

最后这部分是实战中的高频问题,每一个我都亲眼见过或者亲手修过。按“症状—原因—解决办法”整理成表,方便你遇到问题时直接查。

5.1 Agent 高频故障速查表

症状常见原因排查与解决
模型反复调用同一工具,陷入死循环缺少迭代步数上限;工具结果让模型产生了误解设置 remaining_steps 上限;检查工具返回结果是否清晰,必要时给结果加一条“已成功/已失败”的判定字段
模型该调用工具时不调用工具描述模糊;模型能力不足以理解复杂指令重写工具描述,明确触发场景和触发条件;换更强的模型或换一个更擅长工具调用的系列
工具返回结果很长,token 消耗暴涨没有对工具输出做截断工具节点里限制返回给模型的字符数;把大数据量的查询拆成“先确认数量,再分批取详情”
模型连续跟用户确认“你确定吗”系统提示词里没有明确约束;模型不确定性太高在系统提示词里写明“能查就查,不要反复确认”;降低模型温度;检查工具定义是否覆盖了所有必要参数——如果每次都要追问才能凑齐参数,不如让工具支持默认参数兜底
多工具场景下总是选错工具工具签名的描述太接近;工具数量太多拉大不同工具描述的文字差异;按业务域对工具分组,让模型先选组再选工具;必要时升级为多 Agent,各 Agent 只挂一组工具
任务执行到一半,模型忘了最初目标上下文过长,注意力分散;缺少目标追踪用工作记忆保存“任务目标”字段,每一步推理时都放到上下文最前部;必要时每几步总结一次当前进度
生产环境偶发超时Agent 循环次数多,单次执行时间不可控给每一步超时设置上限,整个任务设置看门狗;优化模型选择,比重试更快的通道;考虑用任务化接口替代同步请求,避免用户长时间阻塞

5.2 排查思路:一条完整的止血路径

遇上一个诡异 bug,不要零敲碎打地试提示词。我尝试过很多种方式,最有效的是下面这条路径:

第一步,复现并固定输入。把触发问题的用户输入原样记录下来。第二步,回放全链路日志。看每一步模型输出了什么 thought、调用了哪个工具、工具返回了什么结果。这一步能定位问题是出在模型推理、工具执行还是状态管理。第三步,做局部模拟。把模型输出的内容手动替换成你应该期望的内容,继续往下走,看系统后面能不能恢复正常。这能区分“前面错了导致后面全错”还是“每一步都对但最后没收敛”。

第四步,改了之后一定要跑评测集。很多时候你发现修好了 A 场景,却悄悄破坏了 B 场景。没有评测集的回护,每一步修改都像是在打地鼠。这也是为什么我在决策点部分反复强调评测集的重要,切身体会。

5.3 三个压低故障率的防御性设计

除了问题出现之后的排查,还有几个防御性设计能前置很多麻烦,实测效果立竿见影。

一是给模型“认错退路”。在系统提示词里加一句“如果你发现自己一直重复某个操作,或者连续三次没有进展,直接告诉用户你需要更多信息或建议换一种方式”。这相当于给死循环装了一个逃生门,可以省掉你半夜爬起来杀进程的时间。

二是给工具增加“副作用声明”。在工具描述里注明这个工具是否只是查询还是会产生写入,比如“此操作会向用户发送通知”,模型在决定调用之前就会多一层判断,并且会在最终回答里告诉用户“我已为你保存了备忘录”之类的结果反馈。这个设计可以减少用户困惑和误操作。

三是把危险动作做成显式确认。凡是涉及支付、删除、发送消息这类操作,不要直接让模型调用。改成“模型先生成一个待确认请求,由人工或前端确认后再执行”,这就是经典的 human-in-the-loop 模式。Agent 的定位永远是辅助,最终授权还是得握在人手里。


这套从七要素到七个决策点的拆法,跟网上很多讲 Agent 的文章出发点不同:不追求把概念讲全,只求把你把项目做出来还能上线。我见过太多项目死在过度设计上,也见过死在没设计上。最后有一句话想送给准备上车的你:先跑通一个不完美的 Agent,再逐步把记忆、规划、评测这些模块加进去,边跑边修正,比什么都有效。等你跑完一个完整流程再回来看这七个要素、七个决策点,你会有完全不同的体感——到那时候,你自己就能判断哪些环节该加强、哪些可以继续砍掉了。

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

Agent开发四要素:LLM、Tool、Orchestrator与State工程化实践

1. 这不是“写个Prompt就完事”的玩具&#xff0c;而是工程化智能体的起点“大模型Agent开发入门”——这六个字最近在技术社区里刷屏得厉害&#xff0c;但很多人点开教程&#xff0c;发现讲的还是“用LangChain调用ChatGLM生成天气预报”&#xff0c;或者“让AI自动发邮件”。…

作者头像 李华
网站建设 2026/10/20 23:43:32

QuickBlue:企业级AI应用底座,让AI能力像数据库一样开箱即用

1. QuickBlue 是什么&#xff1f;它不是另一个“AI平台”&#xff0c;而是企业跑AI应用的“地基”QuickBlue 这个名字刚出来时&#xff0c;我第一反应是——又一个包装精美的PaaS平台&#xff1f;结果花两周时间把它的开源仓库、文档和几个典型客户案例翻完后&#xff0c;彻底改…

作者头像 李华
网站建设 2026/10/20 16:48:41

Spring Boot学生选课系统实战:从架构设计到并发控制

从选题到落地&#xff0c;Spring Boot学生选课系统的完整开发展开——这是一篇以毕业设计/课程设计为场景的Spring Boot实战经验分享。我尽量把当初做这个系统时踩过的坑、想明白的道理&#xff0c;以及关键时刻的取舍逻辑都讲清楚。如果你正准备做类似的教务管理类系统&#x…

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

GitHub热点项目精选:如何科学评估与高效使用开源项目

1. 虽然叫“热点精选”&#xff0c;但今天我更想聊聊怎么“选”打开GitHub趋势榜的那一瞬间&#xff0c;确实会有一种“好东西永远看不完”的错觉。每天都有新仓库冒出来&#xff0c;AI、效率工具、Web应用、车载显示、生活方式清单&#xff0c;五花八门。但我在这个时间点集中…

作者头像 李华
网站建设 2026/10/20 10:34:45

LLM-Wiki:把知识库编译成互链网络,用LLM导航检索

开头先交代一个背景。我做了几年的知识库建设&#xff0c;从最早的文件夹归档&#xff0c;到后来的Wiki系统&#xff0c;再到最近的RAG知识库&#xff0c;踩过的坑一个没落下。但直到我把“LLM-Wiki”这个概念真正落地成一套工作流&#xff0c;我才意识到&#xff0c;过去所有的…

作者头像 李华
网站建设 2026/10/30 21:51:41

Qwen-Image-2.1云端部署实战:阿里云+ECS+ModelScope+Gradio一体化方案

1. 项目概述&#xff1a;为什么现在必须认真对待 Qwen-Image-2.1 的云端部署最近两周&#xff0c;我在三个不同客户现场都遇到了同一个问题&#xff1a;本地显卡资源吃紧&#xff0c;但图像生成任务又不能停——设计师要批量出图、电商团队要实时生成商品主图、AI内容团队要跑A…

作者头像 李华