周末下午本来只想给手头几个零散的脚本加个统一入口,结果一不留神就花了两小时顺手搭了个 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 和工具生态
如果你觉得一个个手写函数太累,可以了解一下 MCP(Model 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_key=os.getenv("DEEPSEEK_API_KEY"), base_url="https://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( model="deepseek-chat", messages=messages, tools=TOOLS, temperature=0.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_ascii=False) }) 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 指向 DeepSeek,model 填 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 自动化运维”就是干这个的:把运维工具封装成 API,Agent 根据告警自动排查和修复常见问题。
这个进阶方向要做好权限控制和可观测性。Agent 能调用的工具越多,潜在风险越大。我的建议是:生产环境里先让 Agent 做“建议动作”,由人来确认再执行,跑一段时间没有问题再逐步放权。
5.3 进阶路线:从 Demo 到生产
两小时版本能跑通,但离生产级还有距离。你接下来要补的主要有四块:
- 评估:建立一套测试集,每次改完 prompt 或工具后自动跑一遍,防止“修好一个 bug 又弄坏另一个”。
- 可观测性:记录每一轮的调用链,出了问题能回溯。
- 记忆:引入向量数据库做长期记忆,让 Agent 记住用户偏好和历史状态。
- 多模态:有些工具要处理图片、音频,那就要对接支持多模态的模型,让 Agent 不仅能“看文字”还能“看图说话”。
如果你刚好在找方向,我建议你先做“评估”这一块。很多人把精力花在加新功能上,结果旧功能悄悄退化,等到用户抱怨才发现。提前搭一套回归测试,能省下大量擦屁股时间。
5.4 给新手的建议路线图
最后整理一条适合新手的路线图,按周拆解:
第一周:跑通文中的最小 Agent,改掉它的工具,让它根据你自己的需求做点小事,比如查天气、查快递、算账。第二周:学 n8n 或者 Dify,把一个日常手动流程变成自动流程,重点体会可视化编排和代码方案的差异。第三周:给 Agent 加记忆,用一个简单的向量库存几轮对话,感受“记住你”和“不记得你”的区别。第四周:开始梳理自己工作里最高频的 10 个重复操作,挑 3 个封装成工具,和 Agent 联动。
这条路线不需要你精通机器学习,核心是“会用工具 + 会拆任务”。等你走完一轮,回头看两小时搭的那个 Agent,会发现它确实简陋,但正是这个简陋的起点,让你把一堆抽象概念变成了肌肉记忆。
我个人的体会是,最值钱的反而不是那个能跑通的 Agent,而是过程中建立的调试直觉:你知道模型什么时候会犯错,知道描述怎么写它才会听,知道上下文什么时候会爆。这些经验靠看文档学不来,只能亲手搭一遍。所以我特别建议你今晚就动手,不用等准备好,两小时足够你入门了。