1. 先说清楚:这一篇到底在做什么
这段时间 AI Agent 这个词几乎刷屏了,打开任何技术社区都能看到相关讨论。但大多数教程要么停留在概念层面讲“什么是 Agent”,要么一上来就扔出多智能体框架、复杂编排逻辑,真正零基础的人根本跑不起来。我写这篇的出发点很简单——把手头验证过的一整套搭建流程整理出来,让完全没接触过 AI Agent 的人,也能在半天之内跑起一个真正可对话、可调用工具的智能体。
这篇教程的核心关键词是“零基础可跑”。你不需要提前精通 LangChain,不需要懂复杂的提示词工程,甚至不需要有深度学习基础。我会从概念扫盲开始,逐步带你完成环境准备、模型接入、工具调用、记忆增强这四个关键环节,最终交付一个能实际运行的 Agent 程序。
学完之后你能得到什么?不只是跑通一个 Demo,而是理解 Agent 的核心链路:模型怎么决策、工具怎么被调用、记忆怎么存储。这种能力迁移性很强,后续无论你换什么模型、换什么框架,这套底层逻辑都不会变。废话少说,直接从概念开始。
2. Agent 到底是什么:用大白话拆解核心概念
2.1 从聊天机器人到 Agent:多了什么
很多人以为 Agent 就是能聊天的机器人,这是个普遍的误解。普通聊天机器人是“你说一句、我回一句”的被动应答,而 Agent 的核心特征是自主性和工具使用能力。它不只会说话,还能根据你的目标主动规划步骤,调用外部工具(比如搜索引擎、计算器、API),并基于工具返回的结果继续推理,直到完成任务。
我习惯用一个类比来解释:聊天机器人像一个只有嘴的实习生,能说会道但不会动手;Agent 则像一个有手有脚、会查资料、会做计算的完整员工。你交代他“帮我查一下明天北京的天气然后提醒我带伞”,他会拆解成“查询天气 → 解析结果 → 判断是否需要带伞 → 给出建议”多个步骤,而不是直接瞎编一个天气给你。
2.2 Agent 的三块核心拼图
一个最小可用的 Agent 由三部分构成,缺一不可:
| 组成 | 作用 | 类比 |
|---|---|---|
| 大语言模型(LLM) | 负责理解意图、推理决策、生成回复 | 大脑 |
| 工具集(Tools) | 让 Agent 能获取外部信息或执行动作 | 手脚 |
| 记忆模块(Memory) | 保存对话历史、积累上下文 | 工作笔记 |
这三者之间的关系是:LLM 收到用户输入后,判断当前需要调用哪个工具(或直接回复),把工具返回的信息纳入上下文,再继续推理。这个过程可以循环多次,直到 Agent 认为自己有足够信息生成最终答案。工具闭环是理解 Agent 的关键——没有工具的模型只是“知识的复读机”,有了工具的模型才具备解决实际问题的基础。
2.3 当前主流的技术选型思路
市面上 Agent 开发框架不少,各有侧重。LangChain 生态成熟、文档完善,适合快速验证;AutoGPT 和 BabyAGI 更偏向全自主任务规划,但可控性差;MetaGPT 这类多智能体框架则适合复杂协作场景。
我的个人建议是:零基础入门首选 LangChain 搭配 OpenAI 兼容接口的组合。原因很简单——LangChain 抽象得恰到好处,既不会让你迷失在底层细节里,又保留了足够的灵活性;而 OpenAI 兼容接口意味着你可以用极少的代码切换不同模型服务商,后续成本优化空间很大。下面搭建时我也会用这个组合,并解释每一步为什么这么选。
3. 搭建之前:环境准备与模型接入
3.1 Python 环境:版本和虚拟环境一个都不能错
Agent 开发绕不开 Python。虽说各种语言都有 SDK,但生态最全、示例最多的还是 Python。我这里默认你用的是 Python 3.10 以上版本,这是目前兼容性最好的区间——既支持最新的语法特性,又不会因为太新导致个别依赖还没有适配。
虚拟环境这一步骤建议不要跳过。我见过太多人把依赖直接装进系统 Python 里,最后不同项目之间互相污染,版本冲突查到崩溃。用 venv 创建独立环境只需要两行命令:
python -m venv agent_env source agent_env/bin/activate # Windows 下用 agent_env\Scripts\activate激活后你会看到命令行前缀变成了(agent_env),这表示当前已经在虚拟环境中。后续所有依赖都只会装在这里,干净又安全。
3.2 安装核心依赖:LangChain 生态与框架选择
依赖安装是整个流程中最不容易出错的一步,只要网络正常基本不会碰到问题。我会安装三个核心库:
pip install langchain langchain-openai langchain-community python-dotenv简单说明一下为什么是这三个。langchain是主框架,负责编排整个 Agent 的运行逻辑;langchain-openai是 LangChain 对 OpenAI 兼容接口的适配包,注意不要和旧版的openai包搞混;langchain-community里包含了大量预置的工具和集成,后面注册自定义工具时需要用到。
这里我额外提一个重要配置:很多模型服务商提供的接口是兼容 OpenAI 格式的,这意味着你只需要修改base_url就能无缝切换。在当前这个时间节点,国内可用的模型接口已经非常成熟,大家完全不必纠结“必须用某个国外模型”,按自己实际情况选择即可。
3.3 密钥管理与环境变量配置
接入任何模型服务都需要 API Key。这个 Key 是你的凭证,泄露了就意味着别人可以冒用你的名义调用接口,费用全算在你头上。所以不要把它硬编码在代码里,而是放在.env文件中,并确保这个文件被.gitignore忽略。
.env文件内容大致如下:
OPENAI_API_KEY=sk-你的密钥 OPENAI_API_BASE=https://你的接口地址/v1 OPENAI_MODEL_NAME=gpt-4o-mini # 或你实际使用的模型名在代码中加载这些配置,我习惯在文件顶部统一处理:
from dotenv import load_dotenv import os load_dotenv() api_key = os.getenv("OPENAI_API_KEY") api_base = os.getenv("OPENAI_API_BASE") model_name = os.getenv("OPENAI_MODEL_NAME")这类写法在你迁移到其他机器或更换服务商时会非常方便——只改环境变量文件,不动业务代码。我自己的项目中,不同环境(测试、生产)就是用这一套机制隔离配置的。
4. 手写第一个 Agent:从零搭建最小可运行系统
4.1 设计意图:为什么从“无工具版”开始
现在进入核心环节。我刻意把“无工具版 Agent”放在第一步,因为很多人一上来就同时引入模型和工具,出了问题根本分不清是模型返回格式不对、还是工具注册有误。先跑通一个最小闭环,再逐步加复杂度,这才是正确的排错姿势。
这个最小 Agent 的职责很简单:接收用户输入,调用模型生成回复,返回给用户。虽然没用到工具,但涉及完整的数据流动链路。这就像你要学开车,先在空地跑直线,熟悉油门刹车之后再上复杂路况。
4.2 完整代码与逐行拆解
from langchain_openai import ChatOpenAI from langchain.schema import HumanMessage, SystemMessage import os from dotenv import load_dotenv load_dotenv() # 初始化模型 llm = ChatOpenAI( temperature=0.7, model=os.getenv("OPENAI_MODEL_NAME", "gpt-4o-mini"), api_key=os.getenv("OPENAI_API_KEY"), base_url=os.getenv("OPENAI_API_BASE"), ) # 系统提示词:定义 Agent 的角色边界 system_message = SystemMessage( content="你是一个乐于助人的 AI 助手。回答要简洁准确,不确定时主动承认不知道。" ) # 对话循环 print("Agent 已启动,输入 'exit' 退出") while True: user_input = input("\n你: ") if user_input.lower() == "exit": print("再见!") break # 构造消息列表:系统+用户 messages = [ system_message, HumanMessage(content=user_input) ] # 调用模型获取回复 response = llm.invoke(messages) print(f"\nAgent: {response.content}")这段代码的逻辑非常直观:每次对话都会把系统消息和用户消息打包发给模型,模型返回的内容就是 Agent 的回复。temperature=0.7控制生成随机性,数值越高回答越有创造性、越低越保守。如果你做的是客服系统建议调低到 0.2-0.3,做文案生成则可以调高到 0.8 以上。
跑起来之后,你会发现在这个阶段系统没有任何记忆能力——它不会记得你上一句说了什么。比如你先说“我叫小明”,再问“我叫什么”,它大概率回答不上来。这正好引出下一节的记忆增强。
4.3 让 Agent 学会调用工具:核心进阶
无工具版本跑通后,下面给它装上“手脚”。我用最经典的“自定义工具函数”来演示——让 Agent 能够执行算术运算。这个过程虽然简单,但它把这个核心流程展示得很清楚:模型如何感知到需要调用工具、如何生成调用参数、如何把结果接回上下文。
先看代码:
from langchain_core.tools import tool from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain.prompts import ChatPromptTemplate @tool def calculate(expression: str) -> str: """计算数学表达式。支持 + - * / 和括号,传入表达式字符串如 '1 + 2 * 3'。""" try: result = eval(expression, {"__builtins__": {}}, {}) return f"计算结果: {result}" except Exception as e: return f"计算出错: {e}" tools = [calculate] prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个能调用工具解决问题的助手。需要计算时调用 calculate 工具。"), ("human", "{input}"), ("placeholder", "{agent_scratchpad}"), ]) agent = create_tool_calling_agent(llm, tools, prompt) agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) result = agent_executor.invoke({"input": "计算 23*17+8 等于多少"}) print(result["output"])关键点在第 24 行的{agent_scratchpad}——这是 Agent 中间思考过程的存放位置。模型会先决定“我要调用 calculate”,然后把调用指令写进 scratchpad;工具执行完毕,结果也会回到这里;模型再基于这个结果生成最终回复。你设置verbose=True后就能在控制台看到这一整套完整的推理轨迹,强烈建议第一次运行时开启。
这里我插一句关于eval函数的安全性提醒:上述代码里我特意限制了__builtins__,避免执行任意代码。生产环境中请务必不要直接用eval处理用户输入,改用ast模块解析表达式,或者直接把计算需求限制在加减乘除范围内。
4.4 让 Agent 拥有“工作笔记”:记忆模块接入
没有记忆的 Agent 像金鱼,聊完就忘。LangChain 提供了多种记忆方案,最常见的是ConversationBufferMemory——它会把所有历史消息缓存下来,在每次请求时全部塞给模型。优点是实现简单、无损保留,缺点是对话过长时 token 消耗会快速膨胀。
from langchain.memory import ConversationBufferMemory from langchain.agents import AgentExecutor from langchain.agents import create_tool_calling_agent memory = ConversationBufferMemory( memory_key="chat_history", return_messages=True ) agent_executor_with_memory = AgentExecutor( agent=agent, tools=tools, memory=memory, verbose=True ) # 第一轮对话 result1 = agent_executor_with_memory.invoke({"input": "我叫小明"}) print(result1["output"]) # 第二轮对话,模型应该能记住名字 result2 = agent_executor_with_memory.invoke({"input": "我叫什么名字?"}) print(result2["output"])注意memory_key的定义——在 prompt 模板中需要增加一个对应变量来接收历史记录。我在实际项目中的模板是这样调整的:
prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个能调用工具解决问题的助手。"), ("placeholder", "{chat_history}"), ("human", "{input}"), ("placeholder", "{agent_scratchpad}"), ])这样的效果:每次调用模型时,系统都会把之前所有对话经过打包构造出完整的上下文。代价是 token 消耗随轮数线性增长,对话超过二十轮后一次请求可能要发送几千 token。
对零基础的项目来说这个方案完全够用。但要理解它的局限——真正的生产级 Agent 通常会改用向量数据库做相关检索,只提取与当前问题相关的历史片段,而不是全量塞入。这就是后面“从集中缓存到语义检索”的进阶方向了。
4.5 完整跑通的验收标准
当你把上面代码全部执行成功,并且看到 Agent 能回答你的连续性问题、能正确调用计算工具,恭喜,你已经具备了一个最小 Agent 的完整闭环。
我列一下验收清单,方便你逐一对照:
- 输入“请计算 (12+8)*3” 能返回正确结果 60
- 先告诉它“我的名字是小红”,再问“我叫什么”,它回答小红
- 输入“exit”能正常退出
verbose=True模式下能看到完整的工具调用中间过程
5. 实操验收与踩坑排错实录
5.1 环境类报错的真实排查过程
这部分是我最想分享的。我复盘了近期带新手朋友跑通环境的完整过程,挑出三个最常见的拦路虎。
第一个是版本冲突。LangChain 框架迭代速度极快,0.x 和 1.x 的 API 变化较大。很多网上教程可能用了旧版写法,照抄下来发现from langchain.chat_models import ChatOpenAI直接引入失败。解决办法很简单:安装时直接指定最新版;遇到教程代码报错,优先检查是否为 API 变动导致的导入或调用失败。
第二个是密钥配置没加载。症状表现为请求时报鉴权失败,第一反应总以为是 Key 有问题,但实际上往往只是load_dotenv()没执行成功。最常见的原因:.env文件不在当前工作目录下。用pwd或os.getcwd()确认一下当前位置,别凭感觉判断。
第三个是网络问题导致的连接超时。解决方案思路很简单:LLM 对延迟比较敏感,你可以自己在本机测试一个长连接请求,看是否能连通模型接口。另外注意部分模型服务需要你完成企业/个人的实名认证流程,没有认证时会出现“无权使用该模型”的报错。
5.2 运行逻辑类报错的典型场景
代码跑起来了、环境也没问题,但 Agent 行为怪异,这通常属于逻辑类问题。我把排查清单按优先级列在下面。
症状一:Agent 不调用工具,直接硬答
这时候先看verbose输出,判断模型是否产生了工具调用指令但是工具名不匹配。大概率是工具描述写得太模糊。例如你的工具在繁杂代码里没有说明适用场景,模型就感知不到何时该用。解决办法是把工具描述写得更具体,告诉模型“当用户请求涉及数学计算时,必须使用此工具”。
症状二:工具结果拿到后 Agent 不会用
这类问题的典型现象:模型调用了计算函数拿到“计算结果:60”,但接话时却分析成别的答案。原因多半是工具返回内容的格式不够结构化。改进方案是让工具返回带标签的文本,比如“CALC_RESULT: 60”,模型能更清楚地识别。
症状三:多轮对话出现上下文错乱
这种情况往往出现在记忆模块接入之后。检查你 prompt 模板里的变量名是否和memory_key保持一致。举例——记忆用的 key 是chat_history,但模板里写成history,那么记忆内容永远不会被塞入提示词。
我把这些常见问题汇总成一个速查表,建议截图保存:
| 现象 | 排查方向 | 处理建议 |
|---|---|---|
| 依赖导入报错 | 框架版本不匹配 | 查看官网最新 API,升级代码匹配 |
| 请求返回鉴权失败 | Key 或接口地址问题 | 先确认.env是否加载成功 |
| 模型不调用工具 | 工具描述不清晰 | 强化描述,注明触发条件 |
| 调用了但结果不对 | 工具返回格式问题 | 规范化输出,让模型更容易理解 |
| 多轮对话记忆失效 | key 变量不匹配 | 统一 memory_key 与模板变量名 |
| 响应过慢 | 模型上下文过长 | 换长上下文模型或做记忆裁剪压缩 |
5.3 三个独家调试技巧
技巧一:打印中间轨迹。任何时候搞不清楚 Agent 在做什么,就把verbose=True打开。它显示的内容远比任何 debug 日志直观。如果你用的是 LangChain,我建议直接在AgentExecutor里把日志定位到DEBUG级别,这样能看到工具调用的入参和返回的完整数据。
技巧二:先用“死数据”测试工具函数。注册进 Agent 之前,先在外部把工具函数单独调用一遍,确认输入输出符合预期。很多时候问题不是出在 Agent 编排上,而是工具本身就有 bug——在 LangChain 外面直接调试工具要容易得多。
技巧三:把复杂任务拆成多个独立小测试。我曾经试着让一个 Agent 同时完成“计算表达式并查询天气再生成报告”三个任务,结果排错极其痛苦。后来改成三步独立验证:每一步单独测试,全部通过再把它们组合到一个 Agent 里。这个习惯帮我节约了大量时间。
6. 练手项目与进阶方向
6.1 三个适合练手的实战项目
跑通基础 Demo 之后,直接上复杂项目是最常见的劝退点。我建议你用梯度递进的方式选项目,这里给出三个方向。
第一个方向:个人知识库问答 Agent。把一份 Markdown 笔记(或几个文本文档)做切分后存进向量库,让 Agent 能针对笔记内容回答问题。这个项目会逼你接触文档切分、向量化、相似度检索这些核心概念,而且产出非常实用——每天都能拿它来检索自己的笔记。
第二个方向:带搜索能力的资讯聚合 Agent。给你的 Agent 接上搜索工具接口,让它根据用户提问先检索相关资料再生成回答。这个项目的难点在于结果相关性排序和答案引用标注,完成后你对“RAG(检索增强生成)”的理解会非常扎实。
第三个方向:个人日程助手 Agent。让 Agent 能读取、新增、修改本地日历文件,并用自然语言指令控制。这个项目能让你体会到“工具必须产生的实际效果”——它不像前两个那样只需要“检索和回答”,而是真正产生对外部状态的改变。
6.2 从 Demo 到生产:进阶能力图谱
如果说上面的内容解决的是“把 Agent 跑起来”,那接下来要思考的是“如何让 Agent 在真实环境里稳定可靠”。我梳理了几个核心进阶方向:
从短期会话到长期记忆。ConversationBufferMemory就像一个把全部笔记直接摊在桌面上的做法——迟早会被信息淹没。进阶之后常用的是“摘要记忆”与“向量检索记忆”的组合方案:重要的历史信息定期抽取出摘要,同时把详细内容向量化存储,需要用的时候只检索相关片段。
从单工具调多工具。现实场景中 Agent 通常需要在一轮思考里调用多个工具组合完成任务。这要求你规划好工具的协作关系——哪个先哪个后、依赖哪个结果、反向冲突怎么处理。建议先在代码里列出调用依赖关系,比在模型提示词里硬描述更直观。
从纯语言到结构化输出。生产环境往往需要 Agent 直接产出 JSON 或特定 schema,方便下游系统对接。LangChain 的with_structured_output可以绑定数据模型类,强制模型输出符合格式要求的结构化结果。这块在小项目里可能体验得不明显,但对接正经业务系统时必须掌握。
从单 Agent 到多 Agent 协作。多个 Agent 分工协作、互相传递任务结果是目前行业里热议的方向。但我个人的建议是,如果你连单 Agent 的排查都不够熟练,先不急着上多 Agent 编排。一步一步来,一个能稳定干活的 Agent,远胜于三个互相甩锅的“Agent 团队”。
6.3 持续更新的行业观察
坦率说,AI Agent 这一块的框架和最佳实践变化非常快。上个月大家还在争论该不该引入某种复杂编排,这个月就发现新模型已经原生支持了更强的工具调用能力。我自己的应对策略有三条:第一,不追新框架,只关注自己项目里的实际痛点;第二,每周花一点时间读核心框架的 release notes,提前感知上游变化;第三,多参与开源社区的讨论和 issue 反馈,很多时候别人踩过的坑就是你明天的坎。
7. 从跑通到用好:我的个人经验与建议
写到这里,基础内容已经全部说完了。按惯例分享几个我在多次实操中沉淀下来的心得体会。
第一个是关于学习路径的建议。不要一上来就看高深的多智能体论文,先把今天这套最小闭环玩熟、玩透。你会发现,真正让你成长的不是看教程,而是动手时不断遇到问题、解决问题的过程。每修复一个报错,你对这套系统的理解就加深一层。
第二个是关于成本控制。跑 Demo 时如果不注意,token 消耗速度可能会让你吃惊。建议开发调试时使用支持较高限制的便宜模型,确认逻辑无误后再切换到更高质量的模型。这就像你在本地写代码,先跑单元测试再做灰度环境验证,没必要每一步都上最强的算力。
第三个是关于“Agent 思维”的转变。你最终会发现,写 Agent 的过程更像是在做“产品设计规划”,而不仅是写“代码逻辑”。你需要想清楚它的职责边界、遇到不明确输入时的表现、多轮对话出现偏移时的纠偏策略。这些思考深度决定了你做的 Agent 是玩具还是工具。
我的 GitHub 和博客里一直持续更新 Agent 搭建相关的笔记,如果你在搭建过程中碰到具体报错又排查不出来,欢迎带着完整的错误信息来找我交流。最后送一句自己总结的话:Agent 开发没有玄学,只有你没打印出来的中间轨迹。动起手来,比看十篇教程都有用。