
被“大模型Agent开发入门”这个题目吸引进来的朋友估计和我一样脑子里已经装了无数个名词Function Calling、ReAct、LangChain、Dify、记忆、工具调用……但真正想动手的时候又不知道从哪里下手。我去年底开始做Agent相关项目从只会用Python写死逻辑到今天把一个能查库存、发通知、自动填报表的Agent跑在测试环境里中间踩了不少坑。这篇文章就把我的入门路线、代码思路和避坑清单整理出来给准备入坑的同行一个参考。不管你是后端开发、算法工程师、测试同学还是产品经理只要有一点点Python基础能装Python环境都能顺着这条路线把Agent跑起来。我不打算堆概念而是尽量还原真实的开发过程包括环境怎么搭、模型怎么选、代码怎么写、框架怎么对比、上线前会遇到哪些坑。1. Agent到底是什么和普通API调用有什么区别1.1 从“聊天机器人”到“干活小助手”的质变很多人一开始会把“大模型Agent”和“聊天机器人”划等号。如果只是调API让大模型回答“今天天气怎么样”那是普通的对话充其量叫LLM应用。真正的Agent是把大模型当作“大脑”让它根据目标自主推理、拆解步骤、调用外部工具然后把结果反馈给用户。比如同样是问天气一个普通聊天机器人只会回答“我没办法获取实时天气”而一个Agent会先去调用天气API拿到数据后告诉你“北京今天晴气温-2℃到6℃”。这个“思考-行动-观察-再思考”的循环就是Agent的核心本质。业界经常提到ReAct模式Reasoning and Acting正是把推理和行动交替执行。你可以把它想象成一个新来的实习生领导交代一件事他不会傻坐着而是先理解任务再查资料遇到问题就问然后把结果整理好交给你。Agent要做的就是这套流程只不过“查资料”变成了调用API“问”变成了向模型发出工具请求“整理结果”变成了生成最终回答。1.2 一个最简单的Agent循环是怎么跑的我第一版Agent代码连框架都没用就是用Python手写的一个while循环大致长这样messages [{role: system, content: 你是一个乐于助人的助理。}] max_steps 5 for step in range(max_steps): # 1. 把当前对话历史发给大模型 response llm_client.chat(messagesmessages) content response[content] # 2. 大模型判断是否需要调用工具 if 需要调用工具 in content: tool_name, tool_args parse_tool_request(content) result run_tool(tool_name, tool_args) # 3. 实际执行外部工具 messages.append({role: assistant, content: content}) messages.append({role: tool, content: result}) continue # 4. 如果不需要工具就当作最终回答输出 print(content) break这一步想清楚之后所有框架都只是把上面这个循环包装得更好用而已。我建议你不管最后用什么框架先把这段逻辑写一遍理解“Agent 大模型 工具 循环”这个本质。1.3 几个必须搞懂的基础概念在动手之前下面几个词一定要搞明白否则看文档会一头雾水。Function Calling / Tool Calling大模型输出一个结构化的“调用意图”比如{name: get_weather, arguments: {city: 北京}}。它本身不执行函数只是告诉你的程序“该去调用哪个工具了”。System Prompt放在对话开头用来定角色、定规则。Agent的行为边界一大半靠它控制。记忆MemoryAgent和用户的对话历史。短期记忆是当前上下文窗口内的消息长期记忆则需要外部存储不知道之前聊了什么就没法个性化。上下文长度Context Length模型能同时“看到”的token数量。比如8K、32K、128K超过这个量就得截断或摘要。ReAct一种推理模式——模型每完成一次“想”和“做”再结合观察结果继续下一步。这些概念不用一下子全看懂但看到时要能反应过来后面所有章节都会碰到。2. 环境准备从零拉起一套可复现的开发环境2.1 硬件与模型选型不是所有人都要上A100很多人被“大模型”三个字吓住以为必须买几千块的显卡。其实Agent开发初期完全可以不跑本地大模型。三种常见方案方案成本适合人群代表模型云端API按量付费几十块钱能用很久快速验证想法、不想折腾硬件通义千问、Kimi、DeepSeek、智谱GLM、豆包等本地小模型一台8G显存以上的机器数据敏感、离线环境、长期调优Qwen2.5系列1.5B-14B、Llama 3.2本地大模型加速卡中高成本团队级私有化部署Qwen2.5-72B、DeepSeek系列我的经验是入门阶段优先用云端API。注册一个平台拿到Key就能开始写代码。等到需要频繁测试、大量调用再考虑本地部署也不迟。2.2 用Ollama快速拉起本地模型如果你还是想完全本地跑我最推荐的就是Ollama。它支持macOS、Linux、Windows把模型下载、启动、调用全封装成一条命令。安装好之后在终端执行ollama pull qwen2.5:7b ollama run qwen2.5:7b一个可以在本地对话的模型就跑起来了。它的接口兼容OpenAI格式Python代码可以直接这么连import ollama response ollama.chat(modelqwen2.5:7b, messages[ {role: user, content: 你好介绍一下你自己} ]) print(response[message][content])我之前在一台16G内存的MacBook Pro上跑过7B模型虽然生成速度不算快但用来做功能测试完全够用。如果是企业私有化部署建议上带GPU的服务器跑14B或更大参数模型效果差距明显。2.3 调API和本地模型怎么选不只是成本问题很多初学者会纠结“用哪个”。我踩过一轮坑总结出来的选择逻辑是这样的开发调试阶段用云端API。速度快、模型智商高、不用操心环境先验证流程没问题。数据敏感场景比如企业内部的客户信息、代码库、财务数据这类内容不能出内网。这时候必须本地部署哪怕牺牲一点模型效果。长期成本优化如果每天调用百万级token本地部署的成本边际递减更划算。离线容灾需求有些场景网络不稳定或者需要7x24小时稳定运行本地部署更可靠。另外真正做生产系统时很多人会同时接多个模型简单任务用便宜的小模型复杂推理用强模型。这种“模型路由”的思路可以从一开始就留好接口。2.4 关键参数上下文长度、temperature、top_p刚开始我直接照抄别人的代码完全没管参数结果“nonsense”一堆。后来才意识到Agent本身是不确定系统参数就是它的“性格开关”。temperature温度值越低输出越稳定、越保守值越高越有创造性。做Agent我一般设0.1~0.3宁可让它无聊也不能让它胡编。top_p核采样控制在候选词的概率累计范围。0.9表示每次只从概率最高的一批词里选值越小越稳定。通常和temperature二选一调整不要同时拉满。max_tokens / max_length单次生成的最大token数。如果Agent需要输出代码、JSON、长文一定要给足空间否则会被截断导致解析失败。上下文长度注意模型的最大上下文限制。对话历史太大会超限太小会失忆。后面第5章会细说处理策略。response llm_client.chat( messagesmessages, temperature0.2, top_p0.8, max_tokens1024 )这个参数组合适用于绝大多数Agent场景实测下来既不会太死板也不会乱飞。3. 核心环节实现做一个会查库存、发通知的Agent3.1 明确需求场景先定一个能落地的目标我建议第一个Agent不要做“全能助手”而是做一个“单点任务助手”。我自己的例子是做一个查询库存并发送告警的Agent。它需要知道用户想问哪个商品的库存如果低于阈值就调用发消息的工具通知仓库管理员。场景越具体后面的Prompt、工具设计、测试预期就越清晰。你会很清楚地知道“这个Agent到底跑通了没有”而不是玄学式地“感觉它挺聪明”。3.2 工具注册把外部能力变成大模型认识的方法要让大模型知道可以用你定义的函数需要在请求里传入“工具定义”。以OpenAI风格接口为例tools [ { type: function, function: { name: get_stock_count, description: 查询某个商品的实时库存, parameters: { type: object, properties: { product_id: { type: string, description: 商品ID例如P10001 } }, required: [product_id] } } }, { type: function, function: { name: send_dingtalk_notice, description: 发送钉钉通知给仓库管理员, parameters: { type: object, properties: { message: { type: string, description: 告警内容 } }, required: [message] } } } ]关键点在于每个工具的description要写得非常具体。我一开始写的是“查询库存”模型经常不知道什么时候该调用改成“查询某个商品的实时库存当用户给出商品ID时调用”之后识别率提升一大截。描述文字是模型理解工具用途的重要输入不要偷懒。3.3 实现真正的Function Calling用代码把“动作”接上大模型返回一个类似下面的结构化内容{ role: assistant, content: null, tool_calls: [ { id: call_123, type: function, function: { name: get_stock_count, arguments: {\product_id\: \P10001\} } } ] }你的程序需要解析tool_calls把里面的参数交给注册好的Python函数然后“模拟”一条工具回复消息传回去def execute_tool_call(tool_call, tools_map): func_name tool_call[function][name] args json.loads(tool_call[function][arguments]) result tools_map[func_name](**args) return { tool_call_id: tool_call[id], role: tool, content: str(result) }把执行结果附加到对话历史再继续请求模型模型就会基于工具的实际返回内容生成最终回答。这一步一定要自己手动实现一遍后面不管用什么框架都不会变成“只会改配置的调包侠”。3.4 给Agent加记忆不能聊完就忘很多人忽略了记忆导致Agent一多轮就“失忆”。最简单的短期记忆方案是把历史消息保存在一个列表里每次请求都带上。但列表不能无限长否则很快超过上下文限制。我实测了几种做法滑动窗口只保留最近6-8轮消息。简单直接适合多数场景。摘要压缩每5轮把所有消息丢给模型生成一段摘要然后替换掉旧消息。适合对话很长、需要保留细节的场景。外部向量存储把关键信息写进向量数据库需要时通过相似度检索召回。适合有大量历史知识的情况。初期项目用滑动窗口就够了。真正要落地时我会同时用两种策略滑动窗口保短期向量库做长期记忆。3.5 组装Agent循环从没头没尾的脚本变成一个小系统当我完成工具注册和记忆以后整个代码结构会变得清晰起来分成四个模块agent/ ├── core_loop.py # 主循环负责调度 ├── tools/ # 所有工具函数 ├── memory.py # 记忆管理 └── config.py # 模型、参数配置主循环的核心逻辑依然是“调模型 - 判断工具 - 执行工具 - 再调模型”。我建议把最大循环次数限制在5~8次。因为Agent有时会陷入死循环连续调用同一个工具限制次数能帮你尽早发现异常。for step in range(max_steps): response llm.chat(messagesmessages, toolstools) assistant_msg response.choices[0].message if not assistant_msg.tool_calls: return assistant_msg.content messages.append(assistant_msg) for tool_call in assistant_msg.tool_calls: tool_result execute_tool_call(tool_call, tools_map) messages.append(tool_result)这就是一个最小可用的Agent核心。4. 框架对比LangChain、Dify还是自研4.1 从零自己写自由度最高但要控制复杂度如果你只是写几十行Python完全不需要引入框架。自研的好处是所有细节都受你控制不会出现“框架封装太深出了问题不知道在哪”的窘境。但一旦你要做多Agent协作、条件分支、并行工具调用、长时间任务自己写就容易乱套。我有个同事用自研代码做了六个月后来发现维护成本比业务逻辑还高。所以我的建议是前期自研跑通流程复杂化以后及时切换框架。4.2 LangChain / LangGraph生态丰富但不要被“大而全”迷惑LangChain可能是提到Agent最容易被想到的框架。它内置了Prompt模板、Memory、Tool、Agent类型等一大堆模块。优点是可以快速拼装但缺点是抽象层太厚刚入门会踩很多“类名看懂但不知道干什么”的坑。LangGraph是LangChain团队后来推出的更底层编排框架核心是“图”结构节点是任务边是跳转条件。它把Agent循环可视化了适合做有状态、可分支的复杂任务。如果你是第一次接触我的建议是先不急着用LangChain的Agent封装用它的ChatOpenAI、tool decorator、Memory模块自己搭一个几十行的循环。这样既能利用生态里现成的东西又不至于被它牵着鼻子走。4.3 Dify可视化配置适合产品经理快速验证Dify是一个开源的大模型应用开发平台最大的特点是可视化编排。你在网页上拖拽节点开始节点、大模型节点、工具节点、知识库检索节点、结束节点就能生成一个Agent应用。这种方式特别适合非程序员快速验证也适合团队里让产品经理先画流程再由工程师接入真实代码。Dify可以接入本地模型和多种云端模型还可以通过“自定义工具”的方式接入自己的API。不过它也有代价一旦流程比较复杂图节点的维护成本会比代码高版本管理也不太方便。我的定位是“原型验证工具”生产链路还是用代码更踏实。4.4 我的选型建议按阶段选择我个人的策略是分三步走第1周纯Python 云端API手写ReAct循环完全理解原理。第2~4周引入LangGraph实现工具并行、条件分支、多节点编排。项目需要快速出Demo时用Dify快速搭界面和流程同步用代码重构底层。这个路线看起来“绕路”但实际学习效率最高。你既不会被框架束缚又能在后续规模化时借助框架的能力。对比项自研PythonLangGraphDify学习成本低中高低灵活度高高中适合阶段原理学习、轻量场景生产级复杂编排原型、低代码团队调试难度低中低模块复用自己造轮子生态丰富内置大量工具5. 常见问题与排查技巧实录5.1 AI Agent怎么扛并发从“单线程”到“可扩容”很多人第一次做Agent会遇到性能问题模型返回慢一个请求要几秒甚至十几秒并发一上来直接卡死。这里有几个建议把大模型调用放在异步接口里。不要用同步阻塞的方式等待模型返回用FastAPI的async或异步客户端。给Agent流程设置超时时间。比如单次工具调用3秒模型调用15秒整体循环30秒。宁可超时返回也不要无限等。使用消息队列削峰。Agent和普通接口不一样它不是毫秒级操作。如果业务允许把请求放到Redis或RabbitMQ队列里异步处理前端轮询结果。对模型API做并发池整理。不同任务分配不同并发上限避免某个大任务的慢调用占满所有连接。from fastapi import FastAPI from contextlib import asynccontextmanager import asyncio app FastAPI() async def run_agent(query: str): return await asyncio.to_thread(agent.run, query) app.post(/agent) async def agent_endpoint(query: str): # 异步提交避免阻塞 task asyncio.create_task(run_agent(query)) return {task_id: str(task)}5.2 Token超限与上下文截断最常见的报错就是“This models maximum context length is 8192 tokens”。原因很简单你把整个对话历史都塞进去了。处理方式我已经在前面提过这里再补充一个经验优先提问时截旧消息不要截尾。尾部是模型最近看到的内容对你的当前指令和上下文连续性影响最大。另外可以在对话历史里插入一个system消息提示“之前的信息已经摘要为...”再接入原文模型通常能接受这种“打断”。还有一种情况是工具返回结果太长。比如查询库存接口返回了1000条明细直接塞进消息里很容易撑爆上下文。我在实践中的做法是截断到前50行并在后面追加一句“共1000条已展示前50条如需继续请指定条件”。5.3 模型“偷懒”不调用工具怎么调教新手最容易遇到的问题模型就是不肯调用工具明明用户都说了“查一下A商品库存”它偏偏回答说“我无法查询实时库存”。是我的话会按这个顺序排查检查工具定义中的description是不是太模糊没有触发条件。改成“当用户询问任何商品库存时调用此工具”。给Prompt加先例在系统提示里明确写“你具备查询库存的能力当用户询问库存时必须调用get_stock_count工具”。看模型返回的原始内容有时候模型其实生成了tool_calls但你的解析代码没接住。打印一下原始响应确认是模型问题还是代码问题。换更强的模型小模型1B、3B的指令遵循能力弱经常听不懂“工具调用”要求。换7B及以上问题立刻缓解。5.4 输出格式不稳定JSON解析失败怎么办Agent经常需要输出JSON给下游系统解析。但模型有时会在JSON前后加json标记、加说明文字导致json.loads直接报错。我试过几种应对办法最有效的两步是在Prompt里指定“只输出JSON不要包含任何额外说明或代码块标记”。在代码里写一个贪婪解析函数先用正则找{...}或[...]最外层结构再尝试解析。import re import json def parse_json_response(content: str): # 去掉可能的json 标记 content re.sub(r(?:json)?, , content).strip() try: return json.loads(content) except json.JSONDecodeError: match re.search(r\{.*\}, content, re.DOTALL) if match: return json.loads(match.group(0)) raise ValueError(无法解析模型输出为JSON)5.5 多步任务中的“幻觉”与控制策略AI Agent多步执行时间越长越容易在某个中间步骤“自我发挥”。比如Agent要查库存-生成补货单-发通知结果它跳过了第二步直接发通知。我的体会是不要让模型自己决定“下一步做什么”太开放。给它一个固定的工作流模板比如第1步根据用户问题识别商品ID。第2步调用库存查询工具。第3步判断是否低于阈值。第4步如果低于阈值调用告警工具。第5步生成总结回复。在System Prompt里把步骤一条条写清楚同时限制最大步骤数。对于关键业务动作宁可把流程拆成多个小Agent也不要用一个Agent自由发挥到底。6. 从Demo到落地进阶方向与经验分享6.1 企业私有化部署的取舍最近“企业大模型私有化部署”这个词非常热。如果你们公司已经有内网GPU服务器想部署开源模型我建议按这个顺序做用LM Studio或Ollama在单机上跑通模型。用vLLM或TensorRT-LLM这样的推理引擎部署为HTTP服务吞吐量比Ollama高不少。配置鉴权、限流、监控比如用Prometheus收集请求量、GPU利用率、平均延迟。结合向量数据库如Milvus、Qdrant做知识库检索让Agent能回答私有文档问题。另外纠一个常见认知私有化部署不只是“模型放本地”还包括数据链路、运维、升级。模型版本更新很频繁你要考虑部署脚本是否可持续。我建议把模型文件、推理服务配置、Agent代码都纳入统一的版本管理中。6.2 大模型微调该不该做什么时候做被“大模型微调”吸引进来的人很多但我想泼一点冷水90%的Agent项目不需要微调。在Agent领域效果提升的第一来源是“工程”包括Prompt优化、工具设计、流程编排、记忆策略。微调是后期手段用来解决“同样的问题反复错、且Prompt已经改不动”的情况。比如你发现模型对某个专业名词理解错位而更换Prompt无济于事这时才考虑收集几百条数据做LoRA微调。前期微调不仅成本高还可能因为数据量不足导致灾难性遗忘。6.3 多模态Agent不只是“看图说话”多模态大模型最近进展很快Agent也开始集成图像输入、语音输入。一个简单场景是用户拍一张货架照片Agent识别商品信息然后查库存再发补货单。实现上并不复杂把图片经过编码传给多模态模型接口在Prompt里增加“根据图片识别出商品ID”的指令即可。但要注意图片大小、清晰度、token消耗——一张高分辨率图片转成token后可能占几千token记得在对话里压缩。6.4 给入坑者的最后建议如果你正在考虑要不要学Agent开发我的答案很直接值得但别只学“调API”。把这个领域拆开其实包含三块能力大模型使用能力、工程落地能力、产品设计能力。三块缺一不可。我个人在实际操作中最深的体会是Agent开发百分之六十的时间花在“让模型稳定听话”上剩下的时间才是写业务逻辑。模型本身的不确定性决定了你必须在外部建立各种约束清晰的工具描述、严格的步骤限制、健壮的格式解析、完善的日志追踪。这些东西不是框架能替你做好的只有自己踩过坑才能真正理解。如果你现在还没有环境我建议从今天开始先注册一个云端模型API的Key用Python写一个不到一百行的ReAct循环跑通“查天气”这个例子。一个小时后你大概率会收到第一条“模型成功调用工具”的回执。那瞬间你会觉得原来Agent真的没那么玄乎。