资讯详情

资讯详情

AI Agent从零搭建实战:核心架构、工具调用与Context管理

1. 从零理解AI Agent它到底是什么能帮你做什么这两年“AI Agent”这个词被聊得火热但很多人第一次听到时的反应是不就是个聊天机器人换了个名字吗我刚开始也这么想直到自己动手搭了几个能跑通完整任务的Agent之后才意识到这两者的差距大致相当于“会背菜谱的学徒”和“能独立掌勺的厨师”。先把概念说清楚。AI Agent智能体是一套以大语言模型LLM为决策核心能够自主感知输入、规划步骤、调用外部工具、并根据执行结果调整下一步动作的系统。它和普通对话式AI最大的区别在于对话式AI只负责“回答”而Agent要负责“把事办成”。你问它“今天天气怎么样”它回答你一句话这是对话你说“帮我查一下明天北京的天气如果下雨就提醒我带伞并把提醒写进我的日程”它去调天气接口、判断结果、再调日程接口写入事件这一整套动作才叫Agent。那它到底解决了什么问题我自己的体会是三个字断点。传统的大模型应用能力边界卡在“生成文本”这一步生成完之后要人去复制、去粘贴、去执行。Agent的价值就是把这些断点接上让模型自己决定“下一步该干什么、用什么工具干、干完结果对不对”。适合谁来学我的判断是只要你会写一点代码哪怕是Python入门水平或者你是产品、运营、创业者想搞清楚这套东西能落地到什么场景都值得花时间啃一遍。完全零基础也能看懂原理部分实操部分跟着敲一遍就有感觉。这里必须先把几个高频词捋顺不然后面全是雾水。LLM是大语言模型是Agent的“大脑”负责理解和推理Context是上下文是Agent的“工作记忆”包括对话历史、工具返回结果、系统提示等Tools是工具是Agent的“手脚”比如搜索、计算器、数据库查询、发消息接口。这三者构成了Agent的最小闭环大脑读上下文做决策决策驱动工具执行执行结果再写回上下文。理解了这条链路后面所有的搭建、调优、排错都是围绕这条链路在做文章。2. 拆解Agent的核心架构为什么这么设计2.1 大脑、记忆、手脚的分工逻辑很多人一上来就想写代码我建议先花二十分钟把架构想明白不然写到一半必然推倒重来。Agent的架构本质上是在回答三个问题谁来想、记住什么、怎么动手。“谁来想”就是LLM的选型。这里有个常见误区觉得模型越大越好。实测下来对于工具调用这类结构化任务一个中等规模但指令遵循能力强的模型往往比超大模型更稳、更便宜、延迟更低。原因很简单Agent的核心不是“知识渊博”而是“听话且会拆解步骤”。你让它输出一个JSON格式的工具调用请求它就得老老实实输出JSON不能自由发挥写一段散文。所以选型时指令遵循能力 知识储备这是我踩过坑之后的结论。“记住什么”就是Context的管理。这是整个Agent里最容易被低估、也最容易出问题的部分。Context不是越多越好塞太多历史进去一是贵二是模型会“分心”三是很容易撞上上下文长度上限。我遇到过最典型的一个报错就是this models maximum context length is 1048576 tokens意思是你喂给模型的内容超了。这时候要么做压缩要么做检索把不相关的历史丢掉。Context管理的本质是在有限窗口里放最有用的信息就像你出差只带一个登机箱得挑最关键的装。“怎么动手”就是Tools的设计。工具不是越多越好而是越清晰越好。每个工具要有明确的名称、用途说明、参数定义。我见过有人一口气给Agent挂了二十个工具结果模型选择困难经常调错。后来砍到五个核心工具准确率立刻上来了。工具描述要写得像给新员工看的操作手册含糊的描述会让模型瞎猜参数。2.2 为什么主流方案都采用“循环”而不是“一次性”如果你去看各种Agent框架会发现它们几乎都是循环结构思考→行动→观察→再思考。为什么不是一次性把任务做完因为真实任务几乎不可能一步到位。你让Agent去查资料写报告它得先搜、看结果、发现不够、再搜、再整理。这个“边做边看边调整”的过程就是循环。这个设计背后的逻辑是用不确定性换鲁棒性。一次性生成看起来快但一旦中间某步错了整个结果就废了。循环结构允许Agent在每一步之后根据实际反馈修正方向就像开车时不断微调方向盘而不是闭着眼睛一脚油门到底。代价是更多的模型调用次数和更长的耗时但对于复杂任务这个代价是值得的。我个人的经验是任务越复杂、步骤越多、外部依赖越强循环结构越必要任务越简单、越确定越应该用固定流程而不是让Agent自由发挥。别为了“Agent”而“Agent”一个能用if-else搞定的任务硬套Agent反而更慢更贵更不稳定。2.3 方案选型的几个关键取舍搭建Agent时你会面临几个绕不开的选择我把它们整理成表格方便对照。取舍点方案A方案B我的建议框架选择现成框架如Spring AI Agent、扣子等从零手写学习阶段手写一遍生产用框架工具调用方式模型原生function calling提示词约束输出格式模型支持就用原生更稳记忆管理全量历史塞入摘要检索短对话全量长对话必须压缩执行模式单Agent串行多Agent协作先跑通单Agent别急着上多Agent关于框架我特别想说一句别一上来就上重型框架。我见过太多人连Agent的基本循环都没搞明白就去研究多Agent协作、研究各种高级编排结果出了问题完全不知道从哪查。先用最朴素的方式手写一个能跑的最小闭环把Context怎么传、工具怎么调、结果怎么回填这三件事搞透再去用框架你会发现框架里那些抽象概念一眼就懂了。3. 手把手搭建第一个可用的Agent3.1 环境准备与最小依赖先说环境。Python 3.10以上装一个官方的大模型SDK再装个HTTP请求库就够了。不需要一上来就装一堆东西。我的原则是能少装就少装依赖越少出问题的地方越少。pip install openai requests如果你用的是其他模型服务换成对应的SDK即可。核心就两个能力调模型、发HTTP请求。工具的本质就是发HTTP请求或者执行本地函数没什么神秘的。这里插一句关于环境的坑。有朋友在Windows上跑遇到各种编码问题建议统一用UTF-8文件读写都显式指定编码。还有API Key千万别硬编码在代码里用环境变量这是基本的安全习惯。3.2 定义工具让Agent有手有脚工具的定义要遵循一个原则单一职责、描述清晰、参数明确。我给你一个我常用的工具定义模板以“查询天气”为例。tools [ { type: function, function: { name: get_weather, description: 查询指定城市的当前天气。当用户询问天气、是否需要带伞、穿衣建议时使用此工具。, parameters: { type: object, properties: { city: { type: string, description: 城市名称例如北京、上海 } }, required: [city] } } } ]注意几个细节。第一description里我特意写了“当用户询问……时使用此工具”这是在帮模型判断什么时候该调用非常关键。第二参数描述里给了例子模型看到例子更容易填对。第三required明确标出必填项。这些看起来是小事但实测下来描述写得越细模型调错的情况越少。工具的实际执行函数长这样def get_weather(city): # 实际项目中这里调用真实天气API # 这里用模拟数据演示 mock_data { 北京: 晴25摄氏度, 上海: 小雨22摄氏度 } return mock_data.get(city, 未找到该城市天气数据)提示工具函数一定要做好异常处理。网络请求可能超时参数可能不合法返回结果可能为空。这些异常如果不处理Agent拿到一个报错信息可能会陷入死循环反复重试同一个失败的工具。3.3 核心循环Agent的心跳这是整个Agent最核心的部分我把它拆成清晰的几步。理解了这个循环你就理解了Agent的一切。import json from openai import OpenAI client OpenAI() def run_agent(user_input, max_turns10): messages [ {role: system, content: 你是一个助手可以调用工具帮用户完成任务。请一步步思考需要工具时调用工具。}, {role: user, content: user_input} ] for turn in range(max_turns): response client.chat.completions.create( modelyour-model-name, messagesmessages, toolstools, tool_choiceauto ) msg response.choices[0].message messages.append(msg) # 如果没有工具调用说明任务完成返回结果 if not msg.tool_calls: return msg.content # 有工具调用逐个执行 for tool_call in msg.tool_calls: func_name tool_call.function.name func_args json.loads(tool_call.function.arguments) if func_name get_weather: result get_weather(**func_args) else: result f未知工具{func_name} # 把工具结果写回上下文 messages.append({ role: tool, tool_call_id: tool_call.id, content: str(result) }) return 达到最大轮次限制任务未完成这段代码里有几个关键点值得展开。第一max_turns是必须的。没有这个限制Agent可能在某个错误状态下无限循环烧钱又烧时间。我一般设10轮复杂任务设20轮。第二工具结果一定要写回messages。这是很多人第一次写会漏掉的一步不写回去模型下一轮就“失忆”了不知道工具执行了什么。第三tool_call_id要对上。模型可能一次调用多个工具每个结果必须对应正确的调用ID否则会报schema相关的错误。3.4 跑通第一个完整任务把上面的代码拼起来我们跑一个完整任务试试。result run_agent(帮我查一下北京和上海的天气然后告诉我哪个城市更适合出门) print(result)执行流程是这样的模型先判断需要调用两次get_weather分别查北京和上海拿到两个结果后再综合判断哪个适合出门。整个过程你不需要写任何“先查北京再查上海”的逻辑模型自己会规划。这就是Agent的魅力所在。实测下来这个最小闭环能覆盖相当多的场景查资料、做计算、调接口、整理信息。你先把这个跑通再往上加东西心里就有底了。4. 进阶实战让Agent扛住真实场景4.1 Context管理别让记忆撑爆窗口前面提到的上下文超限问题是实际项目里最常见的拦路虎。当对话轮次多了或者工具返回结果特别长Context就会膨胀。我总结了几个实用的处理策略。策略一滑动窗口。只保留最近N轮对话更早的丢掉。简单粗暴但有效适合大多数短任务场景。缺点是会丢失早期的重要信息。策略二摘要压缩。当历史超过一定长度调用模型把前面的对话总结成一段简短摘要用摘要替代原始历史。这样既保留了关键信息又大幅缩短了长度。我一般设置一个阈值比如历史超过3000字就触发压缩。策略三外部检索。把历史信息存到向量数据库需要时再检索相关片段塞回Context。这个方案适合长周期、多任务的场景但实现复杂度也最高。我的建议是先用滑动窗口不够用再上摘要最后才考虑检索。别一上来就搞最复杂的方案很多场景滑动窗口就够了。4.2 工具调用的稳定性优化工具调用不稳定是新手最头疼的问题。表现包括该调工具时不调、参数填错、调了不存在的工具、陷入重复调用。我整理了一份排查表。问题现象可能原因解决方向该调工具时不调工具描述不清、系统提示没强调在description和system prompt里明确触发条件参数填错参数描述模糊、缺少示例补充参数说明和示例值调用不存在的工具工具太多、命名相似精简工具数量命名区分度要高重复调用同一工具结果没写回、结果格式模型看不懂检查tool结果是否正确回填格式要清晰报schema错误参数类型不匹配严格定义参数类型做好校验我踩过最深的一个坑是工具返回的结果是一大段JSON模型看不懂重点导致它反复调用同一个工具想拿到“更清楚”的结果。后来我把工具返回结果做了精简只返回关键字段问题立刻解决。工具返回给模型的内容要像给人看的简报而不是原始数据 dump。4.3 并发与性能Agent怎么扛住压力“AI Agent怎么扛并发”是个高频问题。单机串行跑一个请求几秒到几十秒并发一上来就崩。我的实战经验是分三层处理。第一层请求队列。所有Agent请求进队列后台worker按能力消费。这样能削峰填谷避免瞬时压力打垮服务。用Redis做队列简单可靠。第二层无状态化。Agent的每一轮状态都存在外部比如Redis服务本身不存状态。这样worker可以水平扩展加机器就能扛更多并发。这一点很关键很多人把状态存在内存里导致没法扩展。第三层超时与降级。每个Agent任务设总超时比如30秒。超时就返回部分结果或友好提示别让用户干等。工具调用也要设单独超时避免某个慢接口拖垮整个任务。注意并发场景下API的速率限制rate limit是绕不开的。做好重试和退避策略遇到限流不要硬刚指数退避重试或者排队等待。4.4 安全边界Agent不能什么都干Agent有手有脚能调工具这就带来了安全风险。我见过有人给Agent挂了“执行系统命令”的工具这非常危险。几条底线必须守住。第一工具权限最小化。只给完成任务必需的工具能查的别给写能读的别给删。第二敏感操作要确认。涉及转账、删除、发送这类不可逆操作必须加人工确认环节不能让Agent自主执行。第三输入输出要过滤。用户输入可能包含恶意指令工具返回可能包含敏感信息都要做检查。第四做好审计日志。每次工具调用都记录出问题能追溯。这些不是杞人忧天。Agent的自主性越强越需要边界。就像你给新员工放权也得有审批流程兜底。5. 常见问题与排查技巧实录5.1 报错速查与应对实际开发中会遇到各种报错我把高频的整理出来方便你对照排查。报错关键词含义处理方式maximum context length上下文超长压缩历史、精简工具返回provider rejected the request schema请求格式不符检查工具定义和消息格式failed to initialize the context上下文初始化失败检查内存和输入数据CORS policy / not a secure context跨域或安全上下文问题检查请求来源和协议connection timeout连接超时检查网络和接口可用性遇到报错第一件事是看完整错误信息别只看第一行。很多关键线索在后面。第二件事是定位是模型侧还是工具侧。模型侧的问题通常是格式和描述工具侧的问题通常是网络和参数。5.2 那些文档里不会写的坑分享几个我实际踩过的坑都是文档里找不到的。坑一模型“假装”调用了工具。有时候模型会在回复文本里写“我已经帮你查了天气”但实际上根本没发起工具调用。这种情况通常是系统提示没写清楚或者模型能力不足。解决办法是在系统提示里明确要求“必须通过工具调用获取信息不能凭记忆回答”。坑二工具返回空结果导致死循环。工具返回空模型以为没查到又调一次还是空无限循环。解决办法是工具返回空时给一个明确的“未找到”提示并在系统提示里说明“如果工具返回未找到不要重复调用”。坑三多工具并行调用时结果错位。模型一次调了三个工具结果回填时顺序错了导致张冠李戴。解决办法是严格用tool_call_id对应不要靠顺序。坑四中文参数编码问题。某些接口对中文参数处理不好导致查询失败。解决办法是参数做URL编码或者改用英文参数。5.3 效果调优的实用技巧Agent跑通不难跑好难。几个调优方向。系统提示是重中之重。我花在写系统提示上的时间比写代码还多。好的系统提示要包含角色定位、能力边界、工具使用规则、输出格式要求、异常处理原则。写得越清楚Agent表现越稳。给例子比讲道理管用。在系统提示里放一两个“用户问X你应该调Y工具返回Z格式”的示例模型模仿能力很强效果立竿见影。控制工具数量。前面说过五个左右是甜点区。超过十个准确率明显下降。如果确实需要很多工具考虑分组或者用路由先判断该用哪组。做好日志和回放。每次Agent执行都记录完整的消息流出问题时能回放这是排查问题的命根子。我一般把每轮的messages都存下来方便复盘。6. 学习路线与场景延展6.1 从入门到进阶的路径如果你刚接触我建议按这个顺序走。第一步跑通最小闭环就是本文第3节那个例子理解循环、工具、上下文三件事。第二步加真实工具接一个真实API处理真实的成功和失败。第三步做Context管理处理长对话和超限问题。第四步优化稳定性把工具调用准确率提上去。第五步考虑并发和部署让Agent能对外服务。第六步探索多Agent协作处理更复杂的任务分解。每一步都别跳。我见过太多人卡在第三步之前就去做第六步结果基础不牢问题一堆。6.2 能落地的场景举例Agent能干的活比你想的多。举几个我实际见过或做过的场景。信息聚合类定时抓取多个来源的信息整理成简报。比如每天早上汇总行业新闻这个用Agent做非常合适因为它需要判断哪些信息相关、怎么归类。流程自动化类把重复的多步骤操作串起来。比如收到邮件后自动提取关键信息、查询相关数据、生成回复草稿。这类场景Agent的价值在于处理“非结构化输入”。辅助决策类根据多个条件综合判断给出建议。比如根据天气、日程、交通情况建议出行方案。这类场景要注意Agent给的是建议最终决策权要留给人。内容处理类批量处理文本比如分类、摘要、改写。这类任务Agent能大幅提效但要做好质量抽检。6.3 关于多Agent协作的冷静看法多Agent协作听起来很酷但我建议你先别急着上。多Agent的核心问题是通信成本和协调复杂度。两个Agent互相传话很容易出现信息丢失、责任不清、循环等待。我试过用多Agent做一个任务结果调试时间比单Agent多了三倍效果还没单Agent好。什么时候真的需要多Agent当任务能清晰拆分成独立且专业的子任务且子任务之间交互很少时。比如一个Agent专门查资料一个专门写代码一个专门做审核各干各的最后汇总。如果子任务之间需要频繁来回沟通那还不如用一个Agent加更多工具。我个人的体会是单Agent加好工具能解决80%的问题。多Agent是那20%复杂场景的解法不是默认选项。别被概念带偏能解决问题的架构就是好架构哪怕它只有一个Agent。最后分享一个我常用的调试小技巧当Agent行为不符合预期时把完整的messages打印出来逐条看模型看到了什么、做了什么决策。十有八九问题就出在某条信息模型没看到或者某条信息表述有歧义。Agent调试的本质就是站在模型的角度看它接收到的信息你会发现很多问题一目了然。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →