ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

两小时搭建AI Agent实战:从零到跑通最小闭环

两小时搭建AI Agent实战:从零到跑通最小闭环 周末下午本来只想给手头几个零散的脚本加个统一入口结果一不留神就花了两小时顺手搭了个 AI Agent。整个过程不算复杂但踩了几个坑也把很多一直模糊的概念彻底理清了。这篇文章就把我这两小时的完整经历写下来包括从零动手的步骤、选型的思路、关键参数的设置以及那些文档里不太会写但特别影响成功率的细节。不管你是刚接触 AI Agent 的新手还是已经玩过一阵子但总卡在“跑不通”“不会调工具”的开发者这篇文章应该都能帮上忙。先说清楚两小时能做什么它不是让你从零训练一个模型也不是搞一套生产级高并发系统而是把“LLM 当作大脑配上记忆、技能和外部工具跑通一个能自动完成指定任务的智能体”。你可以把它理解成给大模型装上手脚让它不再只动嘴而是真的去动手做事情。1. 动手前先想清楚的三件事1.1 AI Agent、LLM、AI 模型到底什么关系很多人一上来就被这几个词绕晕了。我尽量用最直白的方式拆开讲。AI 模型是最大的范畴泛指用数据训练出来的程序能完成识别、生成、预测等任务。LLM 是其中专门处理语言的那一类全称 Large Language Model学的是文字概率分布核心能力是根据上文预测下一个词只是规模大了之后“涌现”出理解、推理、创作等能力。DeepSeek 就是 LLM 的一个具体产品系列它可以是 Agent 的“大脑”但 DeepSeek 本身不是 Agent。Agent 则是一个系统级概念。单个 LLM 只是一个模型让它能主动调用工具、记住上下文、拆解任务并循环执行才算 Agent。用汽车打比方LLM 是发动机Agent 是整车。发动机再强没有变速箱、轮子、方向盘也跑不起来。市面上说的“AI Agent 开发”做的其实就是“给发动机配整车”这件事。这个区别特别重要。因为你会看到很多项目标题是“一行代码接入 DeepSeek”但那只是调模型接口不是 Agent。真正的 Agent 至少要包含模型调用层、工具定义层、循环决策层、记忆管理缺一个都会显得“很笨”。1.2 两小时能搭到什么程度先定目标再动手我不建议任何人抱着“我要做一个改变世界的 Agent”的心态开始。两小时的合理目标是跑通一个最小闭环。我的目标很简单——让 Agent 能理解用户指令自己判断是否需要调用外部工具调用完拿到结果最后把答案整理好返回给用户。这个目标听起来小但已经覆盖了 Agent 的核心循环。我给它加了两个工具查天气、算计算器。测试标准也定得很死用户说“北京今天多少度”它能主动调天气接口并返回结构化答案用户说“帮我算 23 乘 47”它能用计算器工具而不是自己瞎算。后面你会发现这个标准定得好不好直接决定调试效率。给新手一个阶梯感今天跑通主流程本周接 2 到 3 个技能本月把记忆和长期存储补上。两小时不是终点是让你建立“原来 Agent 是这样跑起来”的感觉。1.3 选型代码手搓还是可视化编排这个我纠结了一阵最后两个方案都试了一轮。简单对比方式代表工具优点缺点代码手搓Python OpenAI SDK原理透明、可定制、方便接入自己的系统需要写代码调试较久可视化编排n8n、Dify、Coze上手快、节点拖拽就能跑、内置大量触发器封装较深出问题不好排查结论如果你的目标只是快速做个内部自动化工具不想深究原理用 n8n 或 Dify 完全够。如果你像我一样想弄明白 Agent 内在是怎么工作的我强烈建议先用代码手搓一遍。哪怕只是 100 行对手感和后续排查都有巨大帮助。我这次的做法是先用 Python 手搓主流程再在 n8n 里复现一遍做对比。这样两套都摸过分享出来的内容也更有参考价值。2. Agent 能“干活”的关键五个组成部分2.1 大脑模型选型与参数设置大脑就是 LLM。我用的是 DeepSeek 的 API原因很简单接口兼容 OpenAI 格式文档清楚作为示例跑起来省事。你也可以换 GPT、通义、文心等任何支持 function calling 的模型代码结构基本不变。选型之外参数设置更值得花心思。最容易被忽略的是 temperature。这个参数控制输出的随机性值越大回答越发散值越小越稳定。对于 Agent 场景我们不是要它写诗而是要它按流程执行所以 temperature 建议调低我直接设成 0.2。还有一个隐藏参数是 model 本身是否支持 function calling。DeepSeek 的对话模型和 OpenAI 的 gpt-4o 一样可以通过 tools 参数声明函数模型会根据用户问题主动返回“需要调用哪个函数、参数是什么”。选模型前一定要确认这一点不然你后面的工具调用全部白搭。System prompt 也很关键。它是你在对话开始前给模型设定的“人设”和“行为边界”。我写的是你是智能助手负责通过工具完成用户请求。调用工具前先分析用户意图一次只调用一个工具拿到结果后整理成自然语言。2.2 记忆短期与长期怎么配记忆是 Agent 和“无状态 API 调用”拉开差距的核心能力。它分两层短期记忆就是当前对话的消息历史模型通过上下文窗口“记住”前面聊了什么长期记忆则把重要信息持久化比如存到向量数据库需要时再检索出来。我两小时版本只做了短期记忆——用一个 messages 列表把每次交互都追加进去。实际业务里你会发现这个列表会不断膨胀最后把上下文窗口塞爆。解决办法一般是做滑动窗口只保留最近 N 轮对话或者对旧消息做摘要。这个后面在问题排查部分细说。不要急着上向量数据库。对于大多数个人项目“记最近几轮 把关键信息写进 system prompt”已经能让 Agent 聪明很多了。长期记忆更像是“让我能记住你上次说过的话”属于进阶优化项。2.3 技能让 Agent 做具体的事技能Skill是 Agent 的行动能力。实现上就是定义一个函数然后把这个函数的描述、参数结构告诉模型。关键来了函数描述写得清不清楚直接决定模型会不会调用它。我第一版写的 get_weather 描述是“获取天气”结果模型经常不理会它在应该调用的场景里直接乱答。改成“当用户询问某个城市的天气情况时调用此函数参数 city 是城市名称例如北京”之后调用准确率立刻上来了。原因在于模型是靠描述来决定函数与用户意图的匹配度描述越具体匹配越准确。一个函数的完整定义包括三部分函数名、自然语言描述、参数 JSON Schema。参数 JSON Schema 要注明每个字段的类型和含义模型才能正确提取参数。2.4 连接MCP 和工具生态如果你觉得一个个手写函数太累可以了解一下 MCPModel Context Protocol。它的定位是标准化 Agent 与外部工具、数据源的连接方式。以前每个工具都要自己写适配代码有了 MCP 之后就好比所有外设都统一成了 USB-C 接口插上就能用。MCP 的生态里有大量现成 Server比如连接数据库、读本地文件、调用 GitHub API、查天气等。你只需要跑一个 MCP Server然后在 Agent 端注册一下工具就自动暴露给模型了。对于不想重复造轮子的场景这一步能省掉大量时间。不过我的建议是第一遍学习不要一上来就接 MCP先把工具函数是怎么定义与调用的搞清楚。MCP 只是把“定义函数”这部分标准化了模型调用工具的底层逻辑没变。2.5 编排Agent 怎么决定下一步动作最后一个关键部分就是“循环”。Agent 不是调一次 API 就完事它通常要经历多轮“思考-行动-观察”的循环这就是常说的 ReAct 模式。展开说模型先分析用户意图思考再从可用工具里选一个并生成参数行动拿到工具返回结果之后决定是继续调下一个工具还是整理答案观察。这个循环可能执行多轮所以你必须设置最大迭代次数防止它陷入无限循环。我在代码里就把循环上限设成 5。这样既保证它能完成一些需要两步以上的任务又防止出 bug 时的一次性调用刷爆你的账单。编排层的质量决定了 Agent 是“聪明”还是“死板”耐心调这里收益最大。3. 两小时实操全记录3.1 准备环境与基础依赖我这边的环境很简单Python 3.10 一个虚拟环境。开始之前确保已经装好 openai、python-dotenv 两个库。pip install openai python-dotenv你还需要一个模型 API key。我用的是 DeepSeek 的 key在控制台申请后直接填到环境变量里就行。这一步很容易踩坑key 不要硬编码在代码里更不要提交到 Git 仓库。建一个 .env 文件把 key 放进去代码里通过 os.getenv 读取干净又安全。3.2 写一个最小可用的 Agent先写一个 Agent 的核心骨架。核心逻辑是把用户消息发给模型模型返回两种结果之一——要么直接答题要么要求调用工具。如果是后者执行对应函数把结果回传给模型让它继续。from openai import OpenAI import json import os from dotenv import load_dotenv load_dotenv() client OpenAI( api_keyos.getenv(DEEPSEEK_API_KEY), base_urlhttps://api.deepseek.com ) def get_weather(city: str) - str: 查询天气 return f{city}今天晴25℃ def calculator(expr: str) - str: 计算表达式 return str(eval(expr)) TOOLS [ { type: function, function: { name: get_weather, description: 当用户询问某个城市的天气情况时调用此函数参数 city 是城市名称, parameters: { type: object, properties: { city: {type: string, description: 城市名如北京} }, required: [city] } } }, { type: function, function: { name: calculator, description: 当用户需要数学计算时调用此函数参数 expr 是表达式, parameters: { type: object, properties: { expr: {type: string, description: 数学表达式如 23*47} }, required: [expr] } } } ] def run_agent(user_input: str, max_iterations: int 5): messages [ {role: system, content: 你是智能助手负责通过工具完成用户请求。调用工具前先分析用户意图拿到结果后整理成自然语言回复。}, {role: user, content: user_input} ] for _ in range(max_iterations): resp client.chat.completions.create( modeldeepseek-chat, messagesmessages, toolsTOOLS, temperature0.2 ) msg resp.choices[0].message if msg.tool_calls: messages.append(msg) for tc in msg.tool_calls: fn tc.function.name args json.loads(tc.function.arguments) if fn get_weather: result get_weather(**args) elif fn calculator: result calculator(**args) else: result 未知工具 messages.append({ role: tool, tool_call_id: tc.id, content: json.dumps({result: result}, ensure_asciiFalse) }) continue return msg.content return 达到最大循环次数已终止。 if __name__ __main__: print(run_agent(帮我看看北京天气))这段代码跑通之后恭喜你你已经有了一个最简 Agent。它虽然朴素但模型调度、工具定义、结果回传、循环决策这些要素全都齐了。3.3 测试与调试把“最小可用”练扎实测试用例要覆盖三类场景纯问答、单一工具调用、多步骤任务。我当时的测试清单是“你好介绍一下你自己”——纯问答不调用工具。“北京今天多少度”——触发天气工具。“帮我算 23 乘 47”——触发计算器工具。“北京天气怎么样然后算一下明天如果降温 5 度是几度”——这个需要多轮调用。第一遍跑的时候第 4 个用例直接翻了车。模型在拿到天气结果之后忘了继续计算直接给了一句“明天会降温请注意保暖”就结束了。问题出在 system prompt 里没有强调“必须按步骤执行完所有用户请求”。我加了一句“所有用户明确要求都必须完成不要遗漏任何一步”之后它就正常多了。还有一个细节调试时别急着追求完美。模型偶尔犯错很正常你是在搭框架不是在做学术论文。3.4 用 n8n 复现一遍可视化编排的体验手搓完代码我又花十几分钟在 n8n 里复现了一遍。好处是可以直观看到数据是怎么在节点之间流动的。n8n 里的核心节点是 AI Agent 节点配置思路如下触发器节点选 Webhook 或 Manual Chat用于接收用户消息。AI Agent 节点模型选 OpenAI 兼容接口把 base URL 指向 DeepSeekmodel 填 deepseek-chat。工具节点加两个“HTTP Request”或“Code”节点一个是天气查询一个是计算器。返回节点把 Agent 的最终结果返回给用户。注意 n8n 的 AI Agent 节点自带记忆组件和工具注册机制门槛确实低。但正因为它封装好了一旦调不出结果你反而不知道内部发生了什么。这也是我把“先用代码手搓一遍”放在前面的原因——有了底层手感再用 n8n 就是降维理解而不是黑盒猜谜。3.5 验证与收尾日志和数据控制跑通之后别急着关电脑。把这次运行过程中最关键的数据记录下来调用了多少次 API、每轮模型返回了什么、工具调用是否正确。这些信息在后续优化时特别重要。我当时的记录是单次完整对话平均调用 API 3 次最大迭代轮数 5单次成本约 0.001 元级别。用数据说话后面不管是被问“这玩意贵不贵”还是“会不会失控”你都能直接掏出答案。4. 常见问题与排查技巧实录4.1 API 连接失败或鉴权失败症状是报 401 或连接超时。最常见原因API key 没填对、环境变量没加载、base_url 拼错。排查顺序建议先打印 os.getenv 确认 key 有没有读进来再到官网测试接口连通性最后检查 base_url 是否结尾多了斜杠。4.2 Agent 死活不调用工具这个最让人崩溃。明明定义了工具用户问“北京天气”时它非要自己编一句“北京今天晴”。原因基本集中在三个地方工具描述太模糊模型判断不了意图。system prompt 没有明确“允许并鼓励调用工具”的指令。模型本身不支持 function calling。我的经验是把描述写成“当用户询问XX时调用此函数”再把一个完整示例写进 system prompt 里调用率能提升一大截。另外把 temperature 调低模型会更“听话”不那么发散。4.3 上下文越来越长成本暴涨这是长期运行必踩的坑。messages 列表只加不减几十轮对话之后一次性传给模型的 token 数量可能破万费用和响应时间同时飙升。解决办法给 messages 加一个上限比如超过 20 条就丢弃最早的几条或者把旧对话用模型生成摘要只保留摘要加最近几轮。我自己的习惯是“滑动窗口 关键信息摘要”成本能降一半以上。4.4 角色漂移Agent 开始答非所问明明设置的是“负责通过工具完成用户请求”聊到后面它开始跟你扯闲天甚至输出一些奇怪的内容。这不是模型坏了是 system prompt 的约束力会在长上下文里衰减。解法有两层一是对话每满几轮就重新注入一遍 system prompt二是把“只能执行与工具相关的任务超出范围回复我无法处理”写死。你要是发现角色漂移特别严重优先检查是不是上下文里出现了大量与任务无关的内容把这些内容早点清理掉。4.5 常见问题速查表现象可能原因排查思路401 鉴权失败key 错误或未加载检查环境变量与 key 格式模型不调用工具描述不清/prompt 没引导优化 description写示例调用工具后结果错误参数提取错/函数内部 bug先单独测试函数再走 Agent上下文超长messages 无限制增长做滑动窗口或摘要响应变成乱码返回 JSON 解析失败打印原始返回值不要直接转对象成本太高循环次数太多限制 max_iterations降低冗余轮次5. 两小时之后把 Agent 变成生产力5.1 个人场景自动化办公与信息收集两小时跑通的 Agent 很快就能上手做实际事。我可以让它每天定时汇总几个网站的信息调一个搜索接口或爬虫工具把结果整成简报发到邮箱。你不需要重新训练模型只需要多定义几个工具函数Agent 的能力就扩展了。这类场景的核心思路是“把 Agent 当调度中心把各种 API 当手”。今天加一个邮件发送工具明天加一个日历查询工具它越来越像你的私人助理。5.2 团队场景自动化运维与工单处理如果你所在的团队有大量重复性操作比如查日志、重启服务、批量处理工单Agent 也能直接上手。热词里提过的“AI Agent harness 自动化运维”就是干这个的把运维工具封装成 APIAgent 根据告警自动排查和修复常见问题。这个进阶方向要做好权限控制和可观测性。Agent 能调用的工具越多潜在风险越大。我的建议是生产环境里先让 Agent 做“建议动作”由人来确认再执行跑一段时间没有问题再逐步放权。5.3 进阶路线从 Demo 到生产两小时版本能跑通但离生产级还有距离。你接下来要补的主要有四块评估建立一套测试集每次改完 prompt 或工具后自动跑一遍防止“修好一个 bug 又弄坏另一个”。可观测性记录每一轮的调用链出了问题能回溯。记忆引入向量数据库做长期记忆让 Agent 记住用户偏好和历史状态。多模态有些工具要处理图片、音频那就要对接支持多模态的模型让 Agent 不仅能“看文字”还能“看图说话”。如果你刚好在找方向我建议你先做“评估”这一块。很多人把精力花在加新功能上结果旧功能悄悄退化等到用户抱怨才发现。提前搭一套回归测试能省下大量擦屁股时间。5.4 给新手的建议路线图最后整理一条适合新手的路线图按周拆解第一周跑通文中的最小 Agent改掉它的工具让它根据你自己的需求做点小事比如查天气、查快递、算账。第二周学 n8n 或者 Dify把一个日常手动流程变成自动流程重点体会可视化编排和代码方案的差异。第三周给 Agent 加记忆用一个简单的向量库存几轮对话感受“记住你”和“不记得你”的区别。第四周开始梳理自己工作里最高频的 10 个重复操作挑 3 个封装成工具和 Agent 联动。这条路线不需要你精通机器学习核心是“会用工具 会拆任务”。等你走完一轮回头看两小时搭的那个 Agent会发现它确实简陋但正是这个简陋的起点让你把一堆抽象概念变成了肌肉记忆。我个人的体会是最值钱的反而不是那个能跑通的 Agent而是过程中建立的调试直觉你知道模型什么时候会犯错知道描述怎么写它才会听知道上下文什么时候会爆。这些经验靠看文档学不来只能亲手搭一遍。所以我特别建议你今晚就动手不用等准备好两小时足够你入门了。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进