
1. 从七个零件到七次抉择AI Agent 工程实现的底层逻辑很多人第一次接触 AI Agent 这个概念脑子里浮现的画面大概是科幻电影里那种能自己思考、自己行动、还能跟人唠嗑的智能体。但真到了动手搭建的阶段面对一堆框架文档和术语反而容易懵——到底什么才算 Agent它跟直接调个大模型 API 有啥本质区别我做了几个 Agent 项目之后慢慢摸出一个比较实用的理解方式Agent 本质上就是让大模型在一个循环里自己决定下一步干什么直到任务完成或者触发停止条件。听起来简单但魔鬼全在细节里。一个能跑通的 Agent拆开来看就是七个核心零件在协同工作而要让这七个零件不打架、不空转、不跑偏又需要在七个关键节点上做出正确的工程决策。这篇文章就是把我踩过的坑、试过的方案、以及最后沉淀下来的工程思路完整地摊开来讲。不管你是刚听说 Agent 这个概念还是已经用 LangChain、Spring AI 或者自己手写循环跑过 demo应该都能从中找到一些可以直接抄作业的东西。我会尽量少堆术语多用实际场景和参数选择来说话让不同基础的读者都能看懂、能用上。2. 七个核心要素Agent 到底由什么构成2.1 大模型Agent 的大脑但不是全部大模型LLM是 Agent 的推理核心这一点没什么争议。但很多人容易犯一个错误把 LLM 当成 Agent 的全部。实际上LLM 在 Agent 里只负责一件事——根据当前上下文决定下一步该调用哪个工具、传入什么参数或者直接给出最终答案。选模型的时候我一般会从三个维度来权衡推理能力能不能正确理解工具描述、能不能从多轮对话中提取关键信息。这个直接决定了 Agent 的“智商上限”。响应延迟Agent 是循环执行的每一轮都要调一次模型。如果单次调用要 5 秒跑 10 轮就是 50 秒用户体验直接崩掉。成本Token 消耗在 Agent 场景下会被放大很多倍因为每一轮都要把历史对话和工具定义重新塞进上下文。我实测下来对于工具调用类的 Agent中等规模的模型往往比超大模型更划算。因为工具调用的任务相对结构化不需要模型有太强的开放域推理能力反而对指令遵循和 JSON 格式输出的稳定性要求更高。你可以先用一个大模型跑通流程然后逐步降级测试找到性价比最高的那个档位。注意不要迷信“模型越大效果越好”。在 Agent 场景里一个能稳定输出正确 JSON 的中等模型比一个经常格式跑偏的顶级模型更实用。2.2 工具集Agent 的手和脚工具Tools是 Agent 与外部世界交互的接口。没有工具Agent 就只是一个会聊天的模型有了工具它才能查数据库、调 API、读写文件、发消息。工具的定义方式直接影响了 Agent 的调用准确率。我见过很多项目工具描述写得极其随意比如一个查询天气的工具描述就写“查天气”三个字。结果模型经常在不需要天气的时候也去调它或者传错参数。一个好的工具定义应该包含这几个部分名称用动词开头清晰表达功能比如get_weather_by_city而不是weather。描述说明这个工具做什么、什么时候用、什么时候不用。描述里最好带上使用场景的示例。参数 schema每个参数的类型、是否必填、取值范围、默认值都要写清楚。JSON Schema 是最通用的格式。返回值说明告诉模型这个工具会返回什么结构的数据方便它决定下一步怎么处理。工具的数量也需要控制。我试过给 Agent 挂 20 多个工具结果模型的选择准确率明显下降经常在几个相似工具之间反复横跳。后来精简到 8 个以内准确率就上来了。如果业务确实需要很多工具可以考虑分组或者用路由层先做一次筛选。2.3 记忆系统Agent 的上下文管理记忆是 Agent 工程里最容易被低估的部分。很多人一开始只把对话历史塞进上下文跑几轮之后发现 Token 爆了或者模型开始遗忘早期的重要信息。Agent 的记忆一般分三层短期记忆当前任务的对话历史和工具调用结果。这一层通常直接放在上下文窗口里但需要做截断或摘要。长期记忆跨会话保留的信息比如用户偏好、历史任务记录。这一层通常存在外部数据库或向量库里需要时再检索出来。工作记忆当前任务执行过程中的中间状态比如已经完成了哪些步骤、还剩哪些没做。这一层可以用一个结构化的状态对象来维护而不是全靠模型自己记。我在实际项目里最常用的做法是短期记忆保留最近 N 轮完整对话更早的对话做摘要压缩长期记忆用向量检索只在相关的时候注入上下文工作记忆用一个 JSON 对象显式维护每轮循环都更新。2.4 规划模块Agent 的路线图规划Planning决定了 Agent 是走一步看一步还是先想好整体路线再执行。常见的规划模式有三种ReAct 模式推理和行动交替进行每一步都根据当前观察决定下一步。适合探索性任务但容易陷入局部最优。Plan-and-Execute 模式先制定完整计划再逐步执行。适合步骤明确的任务但计划一旦有误后续全错。混合模式先做粗粒度规划执行过程中根据实际情况动态调整。这是我目前最推荐的方案。规划模块的核心难点在于如何让模型在有限的信息下做出合理的计划同时保留足够的灵活性来应对意外情况。我的经验是在提示词里明确告诉模型“你可以随时修改计划”并且给它一个“重新规划”的工具效果会好很多。2.5 执行器Agent 的动作层执行器负责把模型的决策转化为实际的工具调用并处理返回结果。这一层看起来简单但有几个坑超时处理工具调用可能超时需要有超时机制和重试策略。错误处理工具可能返回错误需要把错误信息结构化后反馈给模型让它决定是重试还是换方案。并发控制有些工具可以并行调用有些必须串行。需要根据工具的特性来设计执行策略。结果截断工具返回的结果可能很长直接塞进上下文会爆 Token。需要做截断或摘要。2.6 循环控制Agent 的心跳循环控制决定了 Agent 什么时候继续、什么时候停止。这是最容易被忽视但最容易出问题的地方。常见的停止条件包括模型输出了最终答案没有工具调用请求达到了最大循环次数达到了 Token 预算上限连续多轮没有实质性进展触发了人工干预我踩过最大的坑就是没有设置最大循环次数结果模型在一个死循环里反复调用同一个工具烧了一堆 Token 才被发现。后来我养成了习惯任何 Agent 循环都必须有硬性的次数上限和 Token 上限这是保底措施。2.7 安全护栏Agent 的刹车安全护栏Guardrails在 demo 阶段经常被忽略但到了生产环境就是必需品。它主要包括输入过滤防止提示词注入攻击输出校验确保模型的输出符合预期格式和内容规范工具权限控制限制 Agent 能调用哪些工具、能访问哪些数据操作审计记录 Agent 的每一步决策和工具调用方便回溯提示安全护栏不是可选项。我见过一个 Agent 因为没做输出校验直接把内部数据库的字段名返回给了用户虽然不是什么敏感数据但足以说明问题。3. 七个决策点工程实现中的关键抉择3.1 决策点一循环用框架还是手写这是每个 Agent 开发者都会面临的第一个选择。用 LangChain、LangGraph、Spring AI 这些框架还是自己手写循环我的建议是先用框架跑通再根据需求决定是否手写。框架的优势在于开箱即用工具定义、记忆管理、循环控制都有现成的实现能让你快速验证想法。但框架的抽象层也会带来问题调试困难、定制化受限、版本升级可能破坏兼容性。手写循环的优势是完全可控每一行代码你都知道在干什么。但你需要自己处理所有细节开发周期会更长。我自己的做法是原型阶段用 LangChain 或 LangGraph 快速搭建验证核心流程到了生产阶段如果框架的抽象层成了瓶颈就把核心循环抽出来自己实现。这样既能快速起步又不会被框架绑死。3.2 决策点二工具调用的粒度怎么定工具粒度太粗模型需要传很多参数容易出错粒度太细工具数量爆炸模型选择困难。我的经验法则是一个工具只做一件事但这件事要有足够的业务完整性。举个例子如果你要做一个电商客服 Agent不要设计一个handle_order工具把所有订单相关操作都塞进去也不要拆成get_order_id、get_order_status、get_order_items这么细。比较好的粒度是query_order查订单、modify_order改订单、cancel_order取消订单这种级别。另外工具的参数设计也很关键。尽量用枚举类型而不是自由文本尽量给参数设默认值尽量让参数名称自解释。这些细节能显著提升模型的调用准确率。3.3 决策点三上下文窗口怎么管理Agent 的上下文消耗比普通对话大得多因为每一轮都要带上工具定义、历史对话、工具调用结果。如果不做管理几轮下来就爆了。我的策略是分层管理内容类型保留策略原因系统提示词始终保留定义 Agent 的角色和行为规范工具定义始终保留模型需要知道有哪些工具可用最近 N 轮对话完整保留保证短期上下文连贯更早的对话摘要压缩节省 Token保留关键信息工具调用结果截断或摘要结果通常很长只保留关键字段工作记忆结构化保留用 JSON 维护任务状态具体 N 取多少取决于你的模型上下文窗口大小和任务复杂度。我一般从 5 轮开始试根据效果调整。3.4 决策点四错误处理策略怎么定Agent 执行过程中一定会遇到错误工具超时、API 返回错误、模型输出格式不对、参数校验失败等等。错误处理的核心原则是把错误信息结构化后反馈给模型让它自己决定怎么办。比如工具调用超时了不要直接抛异常终止而是返回一个结构化的错误信息{ error: timeout, message: 工具调用超时已等待 30 秒, suggestion: 可以重试或者换一个工具 }模型看到这个信息后可能会选择重试也可能会换一个方案。这比直接崩溃要优雅得多。但也要设置重试上限。如果同一个工具连续失败 3 次就应该强制终止或转人工而不是让模型无限重试。3.5 决策点五并发怎么扛Agent 的并发压力主要来自两个方面一是多个用户同时使用二是单个 Agent 内部可能需要并行调用多个工具。对于多用户并发核心是做好资源隔离和限流。每个用户的 Agent 实例应该是独立的共享的只有底层的模型 API 和工具服务。模型 API 通常有速率限制需要做队列和退避。对于工具并行调用需要区分哪些工具可以并行、哪些必须串行。比如查询类工具通常可以并行但写入类工具往往需要串行以保证数据一致性。我实测下来用异步 IO 来处理工具调用能显著提升吞吐量。Python 的 asyncio、Java 的 CompletableFuture、Rust 的 tokio 都是不错的选择。但要注意异步代码的调试难度会高一些需要做好日志和追踪。3.6 决策点六记忆怎么持久化短期记忆放在内存里没问题但长期记忆必须持久化。常见的方案有关系型数据库适合结构化的工作记忆和任务状态向量数据库适合语义检索的长期记忆键值存储适合简单的会话状态缓存文件系统适合小规模、单机的场景我一般会用组合方案工作记忆放 Redis 或内存长期记忆放向量库任务日志放关系型数据库。这样各取所长查询效率也高。3.7 决策点七怎么评估 Agent 的效果Agent 的评估比普通模型评估复杂得多因为它的输出是一个多步骤的过程而不是一个单一的结果。我常用的评估维度包括任务完成率最终有没有完成用户交代的任务步骤效率用了多少轮循环、调了多少次工具工具调用准确率有没有调错工具、传错参数Token 消耗完成一个任务平均消耗多少 Token响应延迟从用户输入到最终输出的总耗时错误恢复能力遇到错误后能不能自己恢复评估方法上我建议先做人工评估积累一批标注数据然后再考虑用 LLM as Judge 来做自动化评估。但要注意LLM 评估本身也有偏差需要定期用人工评估来校准。4. 从零搭建一个最小可用 Agent完整实操流程4.1 环境准备与依赖安装我以 Python 技术栈为例因为生态最成熟上手最快。你需要准备Python 3.10 或以上一个大模型 API 的访问权限基本的网络请求库pip install openai httpx pydantic如果你打算用 LangChain 或 LangGraph可以额外安装pip install langchain langgraph但我建议第一版先手写这样你能真正理解 Agent 的循环是怎么跑的。等跑通了再考虑用框架来简化。4.2 定义工具集我们先定义两个最简单的工具一个查天气一个算数学。import json from pydantic import BaseModel, Field class WeatherInput(BaseModel): city: str Field(description城市名称比如北京、上海) def get_weather(city: str) - str: # 实际项目中这里会调用真实的天气 API mock_data { 北京: 晴25°C, 上海: 多云28°C, 广州: 小雨30°C } return mock_data.get(city, f未找到{city}的天气数据) class CalcInput(BaseModel): expression: str Field(description数学表达式比如 23*4) def calculate(expression: str) - str: try: result eval(expression) return str(result) except Exception as e: return f计算错误{e}工具定义的关键是描述要清晰。模型只能通过描述来理解工具的用途所以描述里要包含使用场景和参数说明。4.3 构建工具注册表工具注册表负责管理所有可用工具并生成模型能理解的工具描述。TOOLS { get_weather: { function: get_weather, description: 查询指定城市的当前天气。当用户询问天气时使用此工具。, parameters: { type: object, properties: { city: { type: string, description: 城市名称比如北京、上海 } }, required: [city] } }, calculate: { function: calculate, description: 计算数学表达式。当用户需要进行数学计算时使用此工具。, parameters: { type: object, properties: { expression: { type: string, description: 数学表达式比如 23*4 } }, required: [expression] } } }4.4 实现核心循环这是 Agent 的心脏部分。每一轮循环我们都要把当前上下文发给模型看它是想调用工具还是给出最终答案。import openai client openai.OpenAI(api_key你的API密钥) def run_agent(user_input: str, max_turns: int 10): messages [ {role: system, content: 你是一个有用的助手可以使用工具来帮助用户。}, {role: user, content: user_input} ] tools_schema [ { type: function, function: { name: name, description: info[description], parameters: info[parameters] } } for name, info in TOOLS.items() ] for turn in range(max_turns): response client.chat.completions.create( modelgpt-4o-mini, messagesmessages, toolstools_schema, tool_choiceauto ) message response.choices[0].message messages.append(message) # 如果没有工具调用说明模型给出了最终答案 if not message.tool_calls: return message.content # 执行工具调用 for tool_call in message.tool_calls: tool_name tool_call.function.name tool_args json.loads(tool_call.function.arguments) if tool_name in TOOLS: result TOOLS[tool_name][function](**tool_args) else: result f未知工具{tool_name} messages.append({ role: tool, tool_call_id: tool_call.id, content: str(result) }) return 达到最大循环次数任务未完成这段代码虽然简单但包含了 Agent 的核心逻辑循环调用模型、执行工具、把结果反馈给模型、直到模型给出最终答案或达到循环上限。4.5 参数选择与调优在实际项目中有几个参数需要根据场景调整参数建议值说明max_turns5-15根据任务复杂度调整简单任务 5 轮足够temperature0-0.3Agent 场景建议低温度保证输出稳定tool_choiceauto让模型自己决定是否调用工具超时时间30-60秒单次模型调用和工具调用的超时重试次数2-3次工具调用失败后的重试上限温度参数特别重要。我试过用 0.7 的温度跑 Agent结果模型经常在工具调用和直接回答之间摇摆输出很不稳定。后来降到 0.1稳定性明显提升。4.6 日志与可观测性Agent 的调试比普通程序难得多因为它的行为是不确定的。所以日志一定要做足。我一般会记录每一轮的完整输入和输出工具调用的名称、参数、结果、耗时每一轮的 Token 消耗最终的任务完成状态这些日志不仅能帮你排查问题还能用来做效果评估和成本分析。5. 常见问题与排查技巧实录5.1 模型不调用工具怎么办这是最常见的问题。模型明明有工具可用却直接用自己的知识回答了。排查思路检查工具描述是否清晰有没有说明使用场景检查系统提示词有没有明确告诉模型“优先使用工具”检查tool_choice参数是不是设成了none尝试在用户输入里加一句“请使用工具查询”我遇到过一次工具描述写的是“查询天气”模型觉得它自己也知道天气就不调工具了。后来改成“查询指定城市的实时天气数据当用户询问天气时使用此工具”调用率就上来了。5.2 工具调用参数传错怎么办模型传错参数通常有两个原因一是参数 schema 描述不清二是模型能力不够。解决方法在参数描述里给出明确的示例用枚举类型限制取值范围在工具函数里做参数校验返回结构化的错误信息让模型重试如果还是不行考虑换一个更强的模型5.3 Agent 陷入死循环怎么办死循环的表现是模型反复调用同一个工具或者在不同工具之间来回跳转始终不给最终答案。解决方法设置硬性的最大循环次数在上下文里加入“你已经调用过这个工具了结果是 XXX”的提示检测到连续多轮没有实质性进展时强制终止在系统提示词里明确告诉模型“不要重复调用同一个工具”5.4 Token 消耗过快怎么办Agent 的 Token 消耗通常是普通对话的 5-10 倍因为每一轮都要带上完整的历史。优化方法对历史对话做摘要压缩对工具返回结果做截断只保留关键字段精简工具定义去掉不必要的描述使用支持更大上下文窗口的模型考虑用缓存来避免重复计算5.5 常见问题速查表问题现象可能原因排查方向模型不调工具工具描述不清、提示词没引导优化描述、加引导语参数传错schema 不清晰、模型能力不足加示例、换模型死循环没有循环上限、缺少进展检测设上限、加检测Token 爆了历史太长、结果太大摘要、截断、精简响应太慢模型延迟高、工具调用慢换模型、异步调用输出格式不对提示词不明确、温度太高加格式说明、降温度提示遇到问题时先把完整的对话日志打出来看一遍。90% 的问题都能从日志里找到原因。6. 进阶方向从能跑到好用6.1 多 Agent 协作单个 Agent 的能力有上限复杂任务往往需要多个 Agent 分工协作。常见的模式有主管- worker 模式一个主管 Agent 负责拆解任务多个 worker Agent 负责执行流水线模式多个 Agent 按顺序处理每个负责一个阶段辩论模式多个 Agent 对同一个问题给出方案然后投票或讨论多 Agent 的难点在于通信和协调。我建议先从简单的两三个 Agent 开始跑通了再扩展。6.2 工具调用的安全加固生产环境的 Agent 必须考虑安全工具调用前做权限校验敏感操作需要人工确认工具返回结果做脱敏处理记录完整的操作审计日志6.3 持续优化与迭代Agent 上线只是开始后续需要持续优化收集用户反馈标注 bad case定期评估任务完成率和效率指标根据评估结果调整提示词、工具定义、模型选择考虑用微调来提升特定场景的效果我个人在实际操作中的体会是Agent 的工程实现没有银弹每个决策点都需要根据具体场景来权衡。但只要你理解了七个核心要素和七个决策点的底层逻辑就能在面对新问题时快速找到方向。最后再分享一个小技巧每次改动只调整一个变量然后对比效果这样才能真正搞清楚每个决策的影响。