AI Agent入门:别急着啃框架,先手写一个最小Agent循环
身边一个做运维的朋友A同学年初决定转行做AI应用开发。他的第一步和大部分人一样收集了各个Agent编排框架的官方文档、翻译版电子书、付费视频课笔记记了两大本还跟着教程敲了好几个Demo。结果呢学了一个多月面对一个简单的报错依然毫无头绪——不知道为什么上下文超限不知道为什么工具调用结果没被模型读到更不知道日志里那一串调用栈在说什么。A同学的困惑很有代表性因为“AI Agent入门”这件事很多人一开始就走反了方向。这篇内容就是写给A同学这样的人刚接触AI Agent的新人、想从其他岗位转过来的开发者。我会直接告诉你AI Agent入门阶段最应该先学的是什么为什么不要一上来就啃框架以及如何在一个月左右建立起真正能用的底层认知。核心观点就一句话框架是给会用的人提高效率的工具不是给新手当教材用的。1. 先搞清楚一件事框架是工具不是知识本体1.1 大多数新手的“框架焦虑”从哪里来打开技术社区满屏都是“基于某某框架搭建智能助手”“用某某框架十分钟做出一个Agent”再一看招聘需求也几乎都写着要熟悉各类Agent开发框架。这种环境下新人很容易产生一种错觉不会框架就等于不会Agent开发学得越早转行越快。但事实恰恰相反。我见过太多人把框架文档当教科书从头到尾翻结果学会的是“怎么调用某个框架的API”而不是“Agent是怎么工作的”。一旦框架升级改版或者公司里换了一套技术栈之前学的百分之七八十都要作废。更麻烦的是框架把最关键的底层逻辑都封装好了你根本看不到模型和工具之间是如何配合的一旦出问题排查起来就像医生只会看化验单却不懂人体结构。1.2 框架替你做了什么你就少了什么市面上主流的Agent编排框架说白了做的事情无非这五类封装大语言模型API的调用请求、重试、流式输出、超时处理。管理对话状态把多轮消息按会话存储、读取、清理。注册和调度工具让你写一个Python函数然后告诉模型“有这个工具可用”。执行Agent主循环判断模型要不要调工具、调完之后把结果喂回去、再让模型继续生成。提供记忆方案对接向量检索、摘要压缩等。这些功能对一个已经理解原理的开发者来说是省时省力的脚手架。但对一个新手来说它们就是一层厚厚的帘子——你把帘子掀开之前根本不知道幕后发生了什么。我打个比方框架像一台自动挡汽车它确实让驾驶变简单了但你连油门刹车离合的关系都没搞明白就坐进驾驶座仪表盘亮一个故障灯你就傻眼。反过来如果你先开一阵手动挡把换挡的逻辑刻进肌肉记忆回头再开自动挡几乎不需要学。AI Agent入门的正确顺序恰恰应该是先用最笨的方式手写一遍Agent的核心循环再去看框架怎么帮你省事。所以第一阶段真正要学的不是某个框架而是大语言模型API本身怎么用、提示词怎么组织、工具调用机制是怎么回事、记忆和上下文怎么管理。这些东西换任何框架都跑不掉。2. 第一课不是写代码是学会“把需求说清楚”2.1 模型是不懂潜台词的实习生很多人第一次调用大模型API只写一句“帮我查天气”然后抱怨模型答非所问。问题不在模型而在你给的信息太少。大语言模型本质上是一个读完海量文本、学会文字接龙的系统它并不天然知道你到底要什么格式的回答、要什么粒度的信息、要什么风格。它像一个特别聪明但完全没有行业常识的实习生你交代任务时少说一个前提它就自由发挥。这也是AI Agent开发者和普通用户最大的区别普通用户可以用聊天式的方式和模型互动但Agent开发者必须把需求“结构化”地表达出来。一个标准的提示词至少要包含三件事角色你是谁你是一个生活助手/数据分析师/客服……任务你具体要做什么查天气、写摘要、还是从文本中抽取信息约束输出格式是什么长度多少不能出现什么举个例子新手可能会写“杭州天气怎么样”模型可能回一大段散文也可能教你带伞信息是散的。但如果你这样写你是我的生活助手。查询杭州今天的天气并回答两个问题 1. 现在的气温是多少 2. 相比昨天是变热还是变冷 要求用两句话以内回答不要输出多余内容。模型答非所问的概率立刻小一半。Agent项目里这种“把需求说清楚”的能力直接影响后续所有环节——因为模型判断要不要调用工具靠的也是你对工具描述的清晰程度。2.2 结构化输出让模型讲“机器听得懂的话”聊天式输出最大的问题是结果不稳定。同一句话这次输出“26摄氏度”下次可能变成“气温26度体感舒适微风”。对人类来说都能看懂但程序不好解析。Agent场景里代码必须按固定字段去读模型的结果。所以入门第二天就应该学会一件事**让模型输出JSON而不是散文。**做法很简单在提示词里写清楚目标数据结构最好再给一个例子。请从用户输入中提取以下字段以JSON格式输出 { city: 城市名称, intent: 用户意图取值只能是weather/reminder/other, keywords: 关键词列表 } 示例输出{city: 杭州, intent: weather, keywords: [天气, 杭州]}如果模型API支持结构化输出参数最好连这个参数也打开。这一步不学后面做工具调用几乎寸步难行因为函数调用的参数本质上就是一种强约束的结构化输出。2.3 上下文窗口你给多少信息决定它干多少活上下文窗口可以简单理解成模型在回答问题时“眼前能看到的文字总量”。Token是它的计量单位一个Token大致相当于半个到四分之三个汉字。窗口越大模型能参考的内容越多但代价也很直接更慢、更贵、注意力更容易被稀释。我见过很多新手犯的错把整个对话历史从第一句开始全部塞给模型每轮都越积越长直到某天窗口爆掉或者模型速度肉眼可见地变慢。这里有一个很朴素的指导思想——最小上下文原则只给模型完成当前这一步任务所需的信息。比如做客服问答历史消息里有200条但用户当前问题只需要最近3轮上下文那就截取最近3轮如果你还想让模型知道用户身份把用户画像摘要拼进去就够了。做Agent开发时上下文管理是一项核心技能因为工具调用的中间结果、模型的思考过程、历史对话全都在跟你抢窗口空间。这个道理懂了后面看框架里的各种记忆组件你一眼就能看明白它们到底在解决什么问题。3. Agent的四个骨架零件缺一个都不是Agent很多人对“Agent”的理解停留在“能聊天、会写文案”的层面这也导致他们看框架文档时目光全落在炫酷的Demo上却忽略了Agent真正区别于普通聊天机器人的地方它是能自己决定调用什么工具、按什么顺序完成任务、并且能记忆和规划的系统。拆开来看一个再复杂的Agent也离不开四个零件模型、工具调用、记忆、规划。入门阶段的重点是先认识工具调用和记忆规划可以往后放一点。3.1 工具调用模型不会动手但它会摇人一个关键认知大模型本身不会执行任何操作它只会生成文本。所谓“工具调用”其实是模型在输出里生成一段特殊指令告诉宿主程序“我需要调用某个工具参数是什么。”宿主程序收到指令后自己去执行真正的代码再把结果作为一条新消息塞回给模型。这个过程可以用一个类比来理解模型像一个项目经理它不会自己搬砖、不会自己查数据库但它知道什么时候该叫电工、什么时候该叫水管工。它开会时说“现在联系施工队进场时间定在明天上午9点”这句话就是一次工具调用。真正给施工队打电话的是旁边的助理——也就是你的宿主程序。所以工具调用里最值得研究的是两件事一是工具描述怎么写二是工具返回结果怎么处理。工具描述写得好模型才能准确判断“什么时候该调用这个工具、参数怎么填”工具结果处理得好模型才能基于真实数据继续回答而不是自己编。3.2 记忆短期工作记忆和长期档案对话场景里的记忆拆开就是两块。短期记忆是当前会话的上下文也就是我们前面说的消息队列长期记忆是把重要信息存到外部系统比如文件、数据库、或者向量检索。短期记忆相当于一个人脑子里正在想着的事长期记忆相当于记在笔记本里的档案。入门阶段先把短期记忆玩明白就足够了你会越来越熟练地管理消息列表知道什么时候该把历史截断什么时候该把工具结果追加进去。至于长期记忆和向量检索我建议把它放到第二个月再研究。原因是向量检索涉及文本嵌入、相似度计算、召回质量评估这是一个独立且不浅的领域上来就搞容易把Agent开发和向量数据库两件事混在一起哪个都没学透。3.3 规划把大任务拆成小步骤规划能力听起来很高级但最朴素的实现方式就是循环让模型看完当前状态决定下一步做什么执行完再让它看结果决定再做什么。经典的模式叫“思考-行动-观察”循环翻译成大白话就是模型先想一步然后调一个工具看看返回结果再想下一步。新手往往把这个想得太玄学总觉得规划必须用什么复杂的算法、专门的推理框架。其实你手写一个while循环就能实现最基础的规划只要模型连续几次判断“任务还没完成我还得继续调用工具”循环就一直往下走。等你能跑通这个循环再回来看框架里的各种规划组件就只是一层更精细的调度罢了。3.4 一个类比Agent像外包团队的项目经理把四个零件串起来最贴切的比喻就是“外包团队的项目经理”。你用户向项目经理模型提需求项目经理手头有一份团队成员通讯录工具列表它知道谁负责什么、该怎么联系接到需求后它开始规划先问设计部要方案再让开发部评估成本最后汇总成一份报告交给你。整个过程中项目文档记忆一直被更新项目经理每一步的决定都基于当前掌握的信息。这个比喻能帮你理清很多模糊概念比如为什么工具描述要写得像“团队成员的技能标签”因为项目经理只能通过这些标签决定该叫谁。为什么上下文窗口很宝贵因为项目经理的桌面就那么大文件摊太多关键材料反而找不到了。4. 不装任何框架手写一个“能查天气”的最小Agent4.1 场景定义一个能查天气并回答的助手说了这么多理论现在动手做一个不需要任何框架、只用Python标准库加一个HTTP请求库就能跑通的最小Agent。目标很朴素用户问“杭州今天天气怎么样适合穿什么”Agent先调用天气工具拿到真实数据再基于数据生成穿衣建议。你可能会问不就查个天气吗直接写个函数然后手动调用不就行了关键是这里多了一个“模型自主决策”的环节——**不是你在代码里显式指定调用get_weather而是模型阅读用户问题后自己决定“该调用天气工具了”。**这一步到位Agent和普通函数的区别就出来了。4.2 从API裸调开始模型本身不会调用工具先把大模型API调用封装成一个函数注意这里的地址和密钥都是模拟值实际使用时替换成你自己对接的模型服务即可import json import requests def call_llm(messages, toolsNone): 极简的大模型API封装仅用于演示 url https://api.llm-example.dev/v1/chat/completions headers { Authorization: Bearer sk-demo-key, Content-Type: application/json, } payload { model: demo-chat, messages: messages, tools: tools or [], tool_choice: auto, temperature: 0.2, } resp requests.post(url, jsonpayload, headersheaders, timeout30) resp.raise_for_status() return resp.json()这里有个容易被忽略的点tools参数是在每次请求的时候都传给模型的。模型并不会“记住”你有这个工具它每次判断时都要靠你在请求里把工具描述完整地带给它。这也是后续上下文变大的原因之一做好心理准备。再写一个模拟的天气查询函数真实项目里改成对服务商API的请求就行def get_weather(city: str) - str: 模拟天气查询实际项目替换为真实服务 if city 杭州: return json.dumps( {city: 杭州, temp: 22, weather: 多云}, ensure_asciiFalse, ) return json.dumps( {city: city, temp: 20, weather: 晴}, ensure_asciiFalse, )4.3 主循环决策、执行、回答现在写Agent的核心循环。先定义工具清单这个清单会随每次请求一起发给模型模型根据它决定要不要调用工具TOOLS [ { type: function, function: { name: get_weather, description: 查询某个城市的当前天气和气温返回JSON字符串, parameters: { type: object, properties: { city: { type: string, description: 城市中文名称例如杭州, } }, required: [city], }, }, } ]注意工具描述里的这句话“查询某个城市的当前天气和气温”。模型不知道你的函数内部逻辑它只能靠这句话来猜“什么时候该调用、参数该怎么填”。所以描述写得越清楚模型瞎调用的概率越低。然后是Agent主循环。逻辑分成两步第一次调用模型看看它有没有在返回里带tool_calls字段如果有就执行对应的工具函数把结果追加到对话里再调用一次模型让模型基于结果生成最终回答。def agent_loop(user_input: str) - str: messages [ { role: system, content: 你是一个生活助手。需要天气信息时调用get_weather获取数据再基于数据回答。回答控制在两句话以内。, }, {role: user, content: user_input}, ] # 第一次调用让模型决定是否调用工具 first_resp call_llm(messages, TOOLS) first_msg first_resp[choices][0][message] messages.append(first_msg) # 如果模型产生了工具调用请求就执行它 if first_msg.get(tool_calls): for tool_call in first_msg[tool_calls]: args json.loads(tool_call[function][arguments]) result get_weather(args[city]) messages.append( { role: tool, tool_call_id: tool_call[id], content: result, } ) # 第二次调用让模型基于工具结果生成回答 second_resp call_llm(messages, TOOLS) return second_resp[choices][0][message][content] return first_msg[content]如果一切正常运行agent_loop(杭州今天天气怎么样适合穿什么)会得到类似“杭州今天22度多云。建议穿长袖或薄外套早晚可以加一件。”的输出。4.4 这个Demo告诉你三件事第一Agent的本质不是什么神秘机制就是一个循环模型决策宿主程序执行结果回灌模型再决策。你把这个循环写熟后面学任何框架都会觉得“原来是这么一回事”。第二工具执行永远发生在宿主进程不在模型内部。模型能做的只是“提出调用请求”真正干活的函数是你的代码。理解这一点你就不会再问“模型怎么自己调用数据库”这种问题。第三tool_call_id必须正确回传。把工具结果追加进messages时每条结果都要关联到对应的工具调用ID。如果漏了这个ID很多模型会直接报错或忽略工具结果。这也是新手第一次手写时最容易踩的坑。我自己当时写完这个Demo最大的感受是以前看框架文档里的“AgentExecutor”“ToolNode”这些概念每个字都认识但不知道在干什么。手写完这个循环之后再看一下就通透了。这就是静态看文档和亲手跑流程的差距。5. 什么时候才应该碰框架以及怎么挑5.1 重复劳动超过三次再考虑框架手写了最小Agent之后你会有一种“代码掌控感”每一行都知道为什么存在。但继续做下去很快会遇到重复劳动每次都要写消息拼接、循环控制、超时重试、历史截断……这时候再考虑引入框架才是正确的时机。我建议给自己设一个信号如果同一个功能你手写了三次以上或者你开始要对多个工具做并发的调度管理那就可以打开框架文档了。因为框架能帮你把繁琐部分抽象掉让你集中精力写业务。而在那之前手写永远是更好的学习方式——学习阶段追求快反而学不到东西。5.2 选框架的标准不是看谁火是看抽象层合不合你的场景市面上的Agent编排框架各有各的抽象方式。有的偏重图形化编排适合产品快速验证有的偏重代码配置适合工程团队深度定制还有的极端贴近底层API几乎就是帮你去掉了重复代码把控制权完全交给你。选择标准其实特别朴素**打开快速开始文档看它让你写的第一个Hello World是什么。**如果我在三步之内就理解了“用户请求进来之后Agent是怎么被创建的、模型是怎么被调用的、工具是怎么被注册的”那这个框架的设计对我来说就是透明的。反之如果文档前两页全是概念名词干了半天也看不到一个能跑通的例子那它对新手来说就是黑盒再火也先别用。5.3 一个被很多人忽略的问题可观测性Agent项目最大的调试难题是你很难知道模型“为什么这么回答”。它可能基于错误的工具结果乱编了一个答案也可能因为上下文里混入了无关信息而跑偏。这时候框架的日志、追踪、中间状态输出能力比任何花哨功能都重要。我见过有人在框架里搭了一个看起来很复杂的Agent一问“如果用户问的问题不在你定义的规划流程里会怎样”答不上来。原因就是框架把他所有的中间步骤都吞掉了他只能看到最终输出完全无法定位。所以选框架时先看看它能不能把“模型输入、工具调用参数、工具结果、模型最终输出”这四个阶段的日志打出来。能就是好框架不能后期有你受的。5.4 自己写轮子的边界在哪强调别一上来就啃框架不代表要永远拒绝框架也不代表所有东西都要手写。我个人的平衡法则是这样把核心的Agent循环保留在自己手里——模型调用、工具决策、结果回灌这三步我的代码里必须看得见、改得动。至于记忆压缩、向量检索、流式输出、队列调度这些外围能力框架怎么方便怎么来。这个边界的意思很简单**一个随时可以拆开重新组装的东西不怕出错。**如果哪天框架升级导致行为变了你至少知道自己的核心逻辑在哪不至于把整个项目推倒重来。6. 一个月的学习路线附老手才会提的避坑清单6.1 分阶段路线规划目标是让一个没有任何大模型开发经验的普通开发者在一个月内具备独立搭建简单Agent应用的能力。路线按周划分不用贪多每周完成一个里程碑就够了。第一周的任务是纯粹打地基注册并配置任意一个大模型API服务学会用代码发起一次对话请求调整temperature、max_tokens等参数观察输出的变化练习写结构化输出提示词让模型稳定输出JSON。这个阶段的验收标准是能不看文档凭记忆写出一段把用户输入转成JSON的API调用代码。第二周进入Agent核心手写一遍上面那个天气查询的最小Agent把工具数量扩展到两到三个比如加一个“查询城市景点”的工具让模型自主决定先查天气还是先查景点在循环里加一个错误处理逻辑比如工具调用参数缺失时让模型重新生成参数。这个阶段的验收标准是你能对着自己的代码讲清楚每一轮循环里消息列表的内容变化。第三周学习记忆和上下文管理给Agent加上“最近5轮对话截断”策略尝试把早期对话做成摘要存入系统提示词如果还有余力了解文本嵌入和向量检索的基本概念。这个阶段不要求你自己实现向量库但要知道它解决的“长期记忆”问题大概是什么链路。第四周挑战框架选一个自己感兴趣但适合新手的框架跑通官方快速开始把你手写的天气Agent用框架重写一遍做一份对比笔记哪些代码被框架接管了哪些逻辑必须自己写。这周结束你已经不是“啃框架”的新手而是“评估框架”的开发者了。6.2 新手最容易踩的几个细节坑下面这几个问题是带过的人几乎都会遇到的提前知道能省很多时间。一是temperature参数没调好。工具调用场景建议设低一点0.2左右让模型输出更稳定。如果设成0.8甚至更高模型会变得“有创造力”工具参数格式错误、意外输出散文的情况会明显增多。入门阶段先追求可控再追求灵活。二是工具描述里的参数含义没写清楚。模型是通过描述来理解“这个参数该填什么”的你写“city: 城市名称”和写“city: 城市中文名称不带省份后缀例如杭州、上海”效果完全不同。描述越具体模型填错参数的概率越低。这不是玄学是每次请求时模型真的在靠这些文字做决策。三是上下文里塞了太多无关历史。新手容易把用户三个月前的闲聊记录一直留着结果导致模型判断工具调用时被干扰。定期截断、定期把旧对话压缩成摘要是Agent开发中最常见也最实用的优化手段。四是JSON解析失败时不处理。模型偶尔会输出不合法JSON前后有额外文字、逗号放错位置都可能让json.loads崩溃。写代码时务必对解析失败做好兜底比如让模型重新输出一次或者从文本里用正则把JSON片段先抠出来。这个处理能直接决定你的Agent是“稳定服务”还是“偶尔罢工”。五是外部工具调用必须设超时。你的天气API、数据库、搜索引擎任何一个挂了都可能彻底拖垮Agent主循环。所有真实的外部请求都要加超时和重试策略同时把这个错误信息作为工具结果回传给模型让它决定下一步怎么办——这本身就是Agent“自主决策”的一部分。6.3 最后的个人体会从我自己带新人的经验来看“AI Agent入门”这件事卡住十个人里七个人的从来不是技术难而是学错顺序。框架文档背得再多代码敲得再快如果不知道模型怎么决策、工具怎么被调用、上下文怎么管理项目一复杂心里必然发虚。而我见过学得最快的路线几乎都是从这个朴素顺序开始的先学会和模型对话再手写一个最简单的Agent循环理解四个骨架零件最后才回头看框架。等你亲手把那几十行代码跑通再打开框架文档你会发现那些曾经像天书一样的术语不过是这个循环的工程化包装而已。放心你的手写Demo会写的比任何框架都简单但它是你的你懂它它也懂你——这才是转行的第一块真正意义上的地基。