AI Agent新手入门:先手写ReAct循环,再谈LangChain和Dify选型
最近几个月我收到最多的私信就是“AI Agent 新手到底怎么入门”,尤其是一些准备转行的朋友,一上来就问我LangChain和Dify哪个好、Agent框架到底该啃哪一个。我每次都会先泼一盆冷水:你先别急着选框架,AI Agent的核心思路都没跑通,盲目啃框架只会让你在抽象层里越转越晕。
AI Agent说白了,就是一个能自主规划、调用工具、根据反馈不断调整行动的智能程序,本质上是“大模型+决策循环+工具库”的组合。这篇文章就是写给刚接触AI Agent的新手,或者准备从传统开发、数据分析转行过来的朋友:我先带你看懂Agent底层是怎么运作的,再给你一条“不依赖任何框架”的入门路径,最后才说框架到底该怎么选、什么时候上。阅读全文大约需要二十分钟,但我建议你跟着实操一遍,比收藏十篇教程都管用。
1. 先搞清楚Agent是什么——新手入门前的心态准备
1.1 Agent的底层三件套:模型、工具、循环
很多新手把Agent想得很玄,觉得它是一个会自己“思考”的超级程序。实际拆开来看,一个最小可用的Agent就三个东西:一个能理解自然语言的大模型,一组能被调用的工具函数,还有一个控制执行流程的循环。
模型负责“想”,工具负责“做”,循环负责“重复想-做直到出结果”。这跟人类解决一道复杂问题的思路非常像:先读题,然后列出步骤,试着执行一步,看结果不对再调整。普通程序是写死的if-else分支,走哪条路完全由程序员预定;Agent则是把“决策权”交给了大模型,让模型根据当前情境临时决定下一步干什么。
举个例子,你给一个传统程序“帮我查北京天气再提醒我带伞”,如果代码里没写“带伞提醒”这个分支,它就做不了。但Agent不一样,它会把任务拆成“查天气-看降水概率-判断是否提醒”,每一步都由模型灵活决策。这个“灵活”既是Agent的亮点,也是Agent的难点——亮点在于它能处理开放任务,难点在于你要花很多功夫教会它别跑偏。
1.2 脱离框架理解主流架构:ReAct是最好上手的起点
讲架构之前先声明,Agent架构在工程领域有很多变体,比如Plan-and-Execute、Self-Refine、Multi-Agent等。但对新手来说,ReAct(Reasoning + Acting)是最值得先弄懂的一个,没有之一。
ReAct的核心是一个循环:Reason(模型根据当前信息进行推理,说明为什么这么做)→ Act(调用某个工具完成一个动作)→ Observe(观察工具返回的结果)→ 再Reason……如此反复,直到模型认为任务完成了。很多框架底层都在做这件事,只是换了个名字而已。
理解ReAct最好的方式,是自己手写一遍这个循环,哪怕只有三十行代码。这也是这篇文章的核心建议:先实现一遍再谈框架。因为只有亲手写过ReAct,你才会真正理解tool_calls是怎么工作的、工具返回结果是怎么喂回模型的、系统提示词在约束模型行为时有多重要——这些基本功如果靠框架掩盖过去,后面做复杂项目时一定会补课。
2. 入门到底该先学什么——知识地图和优先级排序
我见过不少新手陷入一个误区:买课先看LangChain实战,报班先学Dify工作流搭建,结果连system prompt和用户消息怎么拼接都说不清楚。这个顺序是反的。
2.1 一定要先吃透的:提示词工程与上下文管理
Agent的能力上限,很大程度取决于你写提示词的水平。这里的提示词不是“你是一个AI助手”这么一句话,而是包括系统提示词(system prompt)、任务描述、约束条件、示例(few-shot)在内的完整上下文设计。
我说几个新手最容易忽略的细节。第一,系统提示词要写清楚工具使用的边界,比如“只有在用户明确要求查天气时才调用天气工具”,否则模型会在闲聊时也莫名触发工具。第二,工具描述要精确,因为你传给大模型的不是Python函数本身,而是一段描述这个函数功能的JSON,模型靠这段描述来决定要不要调用它,描述写得太模糊,模型就会瞎猜参数。第三,注意上下文的长度限制和成本,每轮对话都会把历史记录重发给大模型,消息太长不光慢,还烧钱,后面要学截断和压缩。
这些听起来平平无奇,但真到实操中,八成以上Agent翻车都是提示词和上下文管理没做好,而不是模型不够聪明。所以我把这块放在最高优先级。
2.2 躲不开的实操课:LLM接口调用与Function Calling
如果连最基本的一次大模型接口调用都没写过,先不要急着碰Agent。你需要先会用代码发起一次chat completion请求,能处理返回的JSON,能处理流式输出(stream),最好还要理解什么是temperature、max_tokens这些参数。这些是Agent的地基,地基不牢,楼盖得再花哨也白搭。
接下来要重点练Function Calling,有的平台叫工具调用Tool Use。这是Agent最关键的机制:你给大模型描述好有哪些工具可用,模型在回答中会返回一个结构化的“我想调用某个工具、参数是什么”的指令,然后你的代码去执行真实函数,再把执行结果返回给模型。整个过程可以理解为模型先写了一张“执行申请单”,你负责去跑腿,然后把跑腿结果拿回来给模型过目,模型再决定下一步。
这个机制难在两点:一是工具函数的输入参数必须能被正确解析和校验,二是工具的执行结果要以正确的消息格式回传给模型,格式错了模型会直接报错或者产生幻觉。这两个坑我后面在实操部分会详细演示。
2.3 先放一放的进阶话题:向量检索、RAG、多智能体协作
网上很多Agent教程喜欢第一课就讲RAG,再讲向量数据库,还给你画一堆多智能体架构图。我建议新手先别碰这些。
为什么?RAG解决的是“给模型补充私有知识”的问题,比如你要让Agent回答公司内部文档里的问题。但它的前提是你已经能跑通一个干净的单Agent循环,否则检索结果回来了、上下文塞进去了,你根本分不清问题出在检索、上下文还是Agent决策上,排查成本直接翻倍。
向量数据库、embedding、多智能体协作,都属于“锦上添花”的进阶能力。我的建议是:花两周时间把单Agent的ReAct循环吃透,再加一点RAG也不迟。基础路径应该像盖楼一样,先框架后装修,而很多人恰恰把装修材料搬进来就开始往里堆,连承重墙都没砌。
3. 框架怎么选——主流Agent框架的真实定位
说到这一步,才轮到框架。我知道大家很关心LangChain、Dify、CrewAI这些名字到底怎么选,先上一张速查表,再解释背后的逻辑。
3.1 一句话看懂LangChain、Dify、CrewAI、MetaGPT
| 框架/工具 | 核心定位 | 适合谁 | 上手难度 |
|---|---|---|---|
| LangChain | 通用开发框架,提供链式调用、工具集成、记忆管理等底层组件 | 有一定开发基础,想深度定制Agent的开发者 | 中等偏难,概念多 |
| Dify | 低代码Agent应用平台,提供可视化工作流编排和大量现成插件 | 产品、运营、非深度开发者 | 低,拖拽即可 |
| CrewAI | 专注于多Agent协作的轻量框架,角色扮演式分工 | 想快速体验多Agent协作场景的人 | 中等 |
| MetaGPT | 模拟软件公司流水线的多Agent框架,强调标准化流程 | 对模拟组织协作感兴趣的人 | 较高 |
从这张表你应该能看出来,它们解决的问题不太一样。LangChain是“乐高积木”,灵活性最高,代价是概念特别多,Chain、Agent、Tool、Memory、OutputParser堆在一起,新手很容易把注意力浪费在框架API上。Dify是“傻瓜相机”,对新手友好,但它帮你封装了太多东西,你能快速做出东西,却很难知道底层发生了什么。这就像会开车和会修车的区别——能用Dify做出Agent,不代表你理解Agent。
3.2 为什么我劝新手别一上来就啃框架
我见过太多这样的案例:一个转行做了三个月的同学,简历上写着“熟练使用LangChain开发Agent”,但你让他解释一下Agent循环里tool_calls是什么、为什么工具返回结果要单独作为tool消息而不是直接拼进用户消息,他答不上来。这不是他的问题,是学习顺序的问题——他被框架推着走,框架替他把复杂的东西藏起来了,他反而失去了理解底层的机会。
框架有一个共性,就是抽象。抽象本身是好事,能把重复劳动屏蔽掉。但问题是,AI Agent这个领域到今天都还没有真正稳定的标准,LangChain的API都可能隔一个版本就变动,你今天啃熟了,过两个月可能又变了。如果你没有底层理解作为“压舱石”,框架一变你等于重新学。
所以我的建议非常明确:入门阶段,框架可以看、可以试用,但不要把你全部精力压在某一个框架上。先用原生代码手写一个最小Agent,你才会知道框架帮你解决了什么、又替你藏起了什么。这也是我常跟新手说的,先学内功,再看招式。
3.3 什么阶段开始碰框架比较合适
具体来说,我会建议新手在满足下面几个条件后再系统学习框架:一是已经手写过一遍ReAct循环,能说清楚大模型、工具、上下文三者的关系;二是至少做过一个能跑通的单Agent项目,哪怕只是一个“天气查询小助手”;三是对提示词工程已经有手感,知道怎么引导模型行为。
满足这三条之后,学框架会非常快,因为你带着问题和需求去学,而不是因为焦虑去学。比如你用原生代码开发Agent时,发现历史记忆管理特别繁琐,这时候再去学LangChain的Memory模块,你会秒懂它解决什么问题;你发现编排多个子任务容易乱,再去试CrewAI,才能体会到它的价值在哪里。
记住:框架是工具,不是知识。知识是Agent的底层原理,工具是帮你省事的捷径。急着拥抱工具,往往是因为不想面对知识。
4. 从零手写一个最小可用的Agent——不装任何框架
说了这么多理念,不如直接动手。这一节我会带你手写一个不依赖任何框架的最小Agent:用户随便问一句话,Agent内部会判断要不要调用天气工具,调用完再结合结果回复用户。这个例子我已经在很多社群分享过,反馈是“比想象中简单,也比想象中更接近本质”。
4.1 准备工作:API、环境、一个具体的任务
先说环境。你需要一个能调用的LLM接口,最方便的是OpenAI兼容接口,市面上也有不少兼容服务商,另外需要一个Python 3.9以上的环境。不需要装LangChain,不需要装Dify,只需要安装openai这个SDK就够了,一条命令搞定:pip install openai。
任务设定很简单:做一个“带天气查询功能的问答Agent”。用户可能会问“北京今天天气怎么样”“明天要不要带伞”这类话。Agent要能识别出用户想查天气,把城市名提取出来,调用一个假的天气查询函数,然后把函数返回的结果组织成自然语言回复给用户。
这里我故意用假的天气数据源,而不是真的去调天气API,因为重点在展示Agent的工作机制,不在网络请求。你把假函数换成真实API请求即可,逻辑完全一致。
4.2 核心实现:写一个带工具调用的ReAct循环
完整代码如下,代码不长,但你认真读完它,比看一百页框架文档都有用:
import json from openai import OpenAI # 模拟工具:返回一个假天气数据 def get_weather(city: str) -> str: data = { "北京": "晴,25°C,湿度40%", "上海": "小雨,20°C,湿度85%", "深圳": "多云,28°C,湿度70%", } return data.get(city, f"暂无{city}的天气数据") tools = [ { "type": "function", "function": { "name": "get_weather", "description": "查询指定城市当天天气情况", "parameters": { "type": "object", "properties": { "city": {"type": "string", "description": "城市名称,例如北京"} }, "required": ["city"] } } } ] functions_map = {"get_weather": get_weather} def run_agent(user_query: str, max_iterations: int = 5) -> str: client = OpenAI() messages = [ {"role": "system", "content": "你是一个有用的助手。请根据工具返回结果生成友好的回复。"}, {"role": "user", "content": user_query} ] for i in range(max_iterations): response = client.chat.completions.create( model="gpt-4o-mini", messages=messages, tools=tools, tool_choice="auto" ) msg = response.choices[0].message messages.append(msg) # 如果没有工具调用,说明Agent认为可以给出最终回复了 if not msg.tool_calls: return msg.content # 依次执行每个工具调用,并把结果以tool消息返回给大模型 for tc in msg.tool_calls: func_name = tc.function.name args = json.loads(tc.function.arguments) result = functions_map[func_name](**args) messages.append({ "role": "tool", "tool_call_id": tc.id, "content": json.dumps(result, ensure_ascii=False) }) return "达到最大迭代次数,Agent任务未完成,请检查提示词或工具定义。" if __name__ == "__main__": print(run_agent("北京今天天气怎么样,我需要提前准备什么吗?"))仔细观察这段代码,三个核心点都被你亲手实现了:一是模型通过tools参数知道有哪些工具可用;二是模型返回的tool_calls告诉你它想调用什么、参数是什么;三是你把工具执行结果以role=“tool”的消息回传给模型,让模型看到结果并生成最终回复。这就是ReAct循环的最简形态,全部加起来不到六十行。
4.3 运行效果与关键细节
这段代码跑起来,可能的输出类似:
北京今天天气晴朗,气温25°C左右,湿度40%,体感比较舒适,没有明显降水概率。这种情况下不需要特别准备雨具,但早晚温差可能略大,建议带一件薄外套。看,模型完成了“理解query→调用天气工具→拿到结果→生成建议”的完整链路。如果我不用工具,只让语言模型直接硬答,它能“编”出天气数据;但有了工具调用,它回答的依据是真实函数返回的结果,从“猜”变成了“查”,这就是Agent和普通聊天机器人的分水岭。
这里有几个新手特别容易踩的细节。第一,json.loads解析参数时要做异常处理,因为模型生成的JSON偶尔会有缺引号、多逗号的情况,我在示例里为了简洁没写try-except,真实项目里一定要加。第二,工具返回的content类型必须是字符串,不能直接传dict,代码里用json.dumps就是为了保证这一点。第三,循环要有迭代上限,防止模型陷入“无限调用工具”的循环烧钱,我设了5次是一个保守值,真实场景按需调整。
5. 新手常见问题实录与避坑指南
到了这一节,我想把实际答疑过程中出现频率最高的问题整理一下,希望能帮你在入门的路上少走弯路。
5.1 高频问题速查表
| 现象/问题 | 原因分析 | 排查/解决思路 |
|---|---|---|
| 模型不调用工具,直接瞎答 | 工具描述不清晰,或模型认为不需要工具 | 检查工具的description和参数说明,让指令更明确,必要时在system prompt里强调“必须调用工具” |
| 模型频繁调用工具,停不下来 | 上下文没有让模型“收尾”的信号,或迭代上限设置过高 | 加迭代上限;在system prompt中说明“确认信息足够后直接回答,不要继续调用” |
| 工具执行结果没有被模型采用 | 工具消息格式不对,或结果内容太长被截断 | 检查role是否为“tool”、tool_call_id是否正确匹配 |
| 多轮对话后Agent开始胡言乱语 | 上下文太长、历史消息未管理 | 引入消息截断、摘要压缩,或参考成熟的memory设计 |
| 参数解析JSON报错 | 模型生成的JSON不规范 | 加try-except捕获,提示模型按schema输出,或使用强类型工具解析 |
| 接口请求超时/限流 | 并发过高或网络不稳定 | 加retry重试机制,控制并发,把超时时间调大 |
这张表不在于罗列全部问题,而是想说明一个规律:绝大多数Agent问题,根源都在“工具定义、上下文管理、循环设计”这三点上。框架可以帮你减少其中的一部分工作量,但框架不能替你理解问题出在哪里。这也是我反复建议先手写一版再上框架的原因。
5.2 我的几点实操心得
最后分享几条我在实际项目里打磨出来的经验,不保证适合所有人,但至少是很多人用真金白银换来的教训。
第一,给工具函数写docstring和description的时候,要用“对模型友好的语言”,不要用“对程序员友好的语言”。模型看不到你的函数内部实现,只能看到工具名和描述,所以你把“查询指定城市当天天气情况”这种描述写得越直白,模型越容易正确调用。
第二,把工具划分得越细,Agent越容易被模型“选错”。有时候你以为多提供几个工具是给模型更多选择,实际上是在增加它的决策负担。新手阶段,宁可使用少量、职责明确的工具,也不要搞一堆参数复杂的万能工具。
第三,日志比想象中的重要。手写Agent的时候,一定要把每一轮的messages、工具调用参数、返回结果都打印出来。很多新手问“为什么模型不按我的要求做”,一看日志就发现,是自己的上下文理解错了,或者工具返回结果本身就不是期望的格式。留日志的习惯,能帮你节省大量试错时间。
第四,别迷信“最新架构”。今天可能有人跟你说GraphRAG很火,明天有人说多智能体是未来,对新手来说这些都是噪音。先把最简单的循环玩明白,再往复杂方向走,你会发现所谓“新架构”说来说去,核心还是那一套模型加工具加循环的底子。
第五,做项目时从“垂直小功能”切入,不要一上来就做一个“万能助理”。我见过太多新手第一个Agent想做个什么都管的全能助手,最后连需求文档都写不清楚。先把“查天气”“查快递”“记笔记”这些单一能力做到稳定,再考虑组合。做得越小,越容易出成果,越容易建立正反馈。
我个人带过不少人从零接触Agent,一个明显的感受是:那些走得最快的人,几乎都不急着炫耀自己用了什么花哨框架,而是愿意在一个最简示例上反复打磨两三天。新手阶段,框架账面上省下的时间,最后往往会在排查底层问题时加倍还回来。踩过这些坑之后我是真的觉得,先手写一个循环,比什么都管用。