1. 别急着装框架,先回答一个扎心的问题
这几年AI Agent的讨论热度一直很高,我身边不少做后端、前端甚至产品经理出身的朋友都在观望转行。大家最容易踩的坑,就是听说某个框架很火,于是第一时间装上依赖、跑起demo,结果玩了三天就卡住了——不知道自己的Agent为什么总是不听话,不知道下一步该学什么,最后只能放弃。
我早期带过几位零基础转行的同事,也看过一些新人在群里问“Agent框架怎么选”“LangChain和LlamaIndex哪个好”。在我看来,这些问题的前提就错了。新手和转行者首先要学的,不是框架,而是Agent背后的那几个核心机制:大模型API的基本用法、提示词工程、结构化输出、工具调用的设计思路,以及最简单的Agent运行循环。这些东西搞明白了,框架只是换一种更方便的写法而已;搞不明白,换多少个框架都是在迷宫里打转。
这篇文章我把自己的入门路径拆开来讲,按“先学什么、为什么先学这个、怎么练”的顺序展开。内容不涉及具体某一家平台,思路适用于目前所有主流大模型API接口,代码示例也尽量保持通用。
2. 搞清楚Agent到底是什么——先把概念层吃透
2.1 Agent不是一个模型,而是一套运行流程
很多新人容易把Agent和大模型划等号,这是第一个容易混淆的地方。大模型是一个会算概率的“大脑”,你给它一句话,它给你一段补全或对话结果。而Agent是一个能自主决策、调用工具、分步解决问题的程序系统——大脑只是其中一个部件。
打个比方:大模型像一个经验丰富但不会动手的顾问,你问他“这个项目该怎么安排”,他能给你列出完整计划;但真正执行计划的人,还得是你或你设计的程序。Agent干的事,就是把“顾问的思考”和“执行者的手”接起来——顾问负责拆解任务、判断下一步做什么,执行者负责真的去调接口、查数据库、发请求、算结果。
所以入门前要建立一个心智模型:
- 大模型负责规划、推理、生成自然语言或结构化数据;
- 程序代码负责解析模型的输出、执行具体动作、读取外部数据;
- 整个循环(思考-决策-执行-观察结果-再思考)构成了Agent的行为闭环。
只要你能把这个闭环跑通,不管你用不用框架,你都已经在做Agent了。
2.2 Agent运行循环里最基本的四个环节
我在给新人讲的时候,习惯把Agent的循环拆成四步:
- 理解任务:把用户的目标整理成模型容易理解的提示词,或者拆成若干子目标;
- 推理规划:模型根据提示词和当前可用的工具,生成下一步要做什么的决策;
- 调用工具:程序解析模型输出中的工具名和参数,真实调用外部API或脚本;
- 观察结果:将工具返回的结果拼回上下文,交给模型,继续决定下一步。
所有框架,无论包装多复杂,核心都逃不开这四步。新人如果一上来就学框架,很容易被框架的抽象概念带偏,根本不知道自己的Agent为什么在某一步卡住。手工把这四步实现一遍,哪怕用if-else搭一个极简版,你对“框架到底做了什么”也会有本质的理解。
2.3 为什么框架对新手反而是负担
这不是说框架没用,而是框架的抽象是给有一定经验的人准备的。新手对底层流程还没感觉的时候,框架里那些概念(如记忆模块、检索增强、多轮对话管理器、工具注册中心)全是费解的黑盒。
举个例子:你问框架“为什么这里没调用搜索工具”,要从回调链、内部Prompt模板、默认参数一层层排查,新人根本无从下手。而你自己写的代码只有三十行,哪里出错一目了然。我建议新人的路线是:先手工实现一遍极简Agent,再尝框架,最后再回到手工实现。走完这一圈,框架在你眼里只是节省代码量的工具,不再是必须依赖的拐杖。
3. 学习的优先级怎么排——一张循序渐进的路线图
3.1 核心知识与具体实践的权重分配
我给自己带的人安排的学习顺序是这样的,供参考:
- 大模型API的调用方式(占比20%):学会发请求、传参数、拿结果,重点掌握system/user/assistant三者的分工;
- 结构化输出与JSON解析(占比25%):让模型输出可被程序读取的格式,这是Agent能自动运行的前提;
- 提示词工程(占比25%):用最少的字把任务说清楚,尤其是怎么写系统提示词和工具描述;
- 简单循环编程(占比20%):不依赖框架,手写一个“调模型、解析结果、执行工具、再调模型”的最小循环;
- 框架选型与阅读(占比10%):最后才看框架,并且只看自己需要的那部分源码。
前四项只要持续练习两三周就能上手,第五项可以延后。很多转行者觉得“不学框架简历不好看”,但实际面试中面试官更在意的是你是否能讲清楚一个Agent的完整链路。框架反而不是重点,因为更新太快,今天学的可能下个月就变了。
3.2 三个必须练到条件反射的基本功
这三个基本功,是我带新人时觉得性价比最高的:
基本功一:让模型说“人话”变成让模型说“机器话”。
Agent里,模型要跟程序配合,所以输出不能是随意的话,最好有固定结构。最常用的就是JSON。你提示词里加一句“只输出JSON,不要解释”,然后用代码去解析。很多新人第一次看到模型输出一段JSON+多余文字,导致解析失败,才意识到“格式约束”是Agent开发里多么关键的议题。
基本功二:把一句话任务拆成子步骤。
比如“帮我把这篇长文总结成要点并翻译成英文”,模型其实要分两步:先用中文总结,再翻译。你要学会在提示词里引导模型按步骤输出,或者在程序里设计两轮调用。这种拆解能力直接决定了Agent能不能做复杂任务。
基本功三:学会看Token用量和上下文长度。
Agent跑几轮之后,对话历史越来越长,很容易超出模型的上下文窗口,或者费用爆炸。新手最容易忽视这个问题,等Agent“突然失忆”或报错时才去找原因。我一般建议所有调用日志里都记录token数,尽早建立成本意识。
3.3 给时间紧张的转行者的一个折中方案
如果你是上班族或者还有课要上,每天最多抽一两个小时,也不用焦虑。最务实的节奏是:第一周只学第一步和第二步,每天写一个小脚本,比如“输入一段天气文字,输出JSON包含温度/湿度/风级”;第二周用提示词把两个小工具串起来,比如先查天气再决定穿什么衣服,不完全用框架。两周能写出一个能跑的极简Agent,你就有信心继续深入了。
4. 核心实操:动手写一个极简但完整的Agent
4.1 环境准备和接口调用基础
实际操作不需要复杂环境,一个Python文件就能跑通。假设你已经能通过某种方式拿到大模型API的访问凭证,配置好环境变量,比如模型接口地址、API密钥等。这里不给具体平台,写法上用普遍兼容的方式。
调用聊天补全接口的基础代码,大致是这个样子:
import os import json import requests # 基础配置:接口地址、密钥、模型名称 API_URL = os.getenv("AGENT_API_URL") API_KEY = os.getenv("AGENT_API_KEY") MODEL = os.getenv("AGENT_MODEL_NAME", "default-model-name") def chat(messages, temperature=0.2): headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json", } payload = { "model": MODEL, "messages": messages, "temperature": temperature, } resp = requests.post(f"{API_URL}/chat/completions", headers=headers, json=payload, timeout=60) resp.raise_for_status() data = resp.json() return data["choices"][0]["message"]["content"]这步看起来简单,但我还是建议新手亲手敲一遍。你会在过程中理解:消息列表是一个数组,里面分了几种角色;system是设定全局行为,user是当前请求,assistant是历史回复。很多人后面调试Agent时发现“模型怎么总记错上下文”,其实往往是最初messages配错了。
4.2 让模型输出可解析的JSON——打通第一道关
在Agent开发里,我们经常要让模型不只回复一句话,还要输出“下一步动作”。最朴素的做法是要求模型在回复中给出JSON,里面包含意图和参数。示例:
SYSTEM_PROMPT = """ 你是一个任务规划助手。用户会提出一个目标,你要把目标拆成分步计划。 只输出JSON,不要输出任何解释性文字。格式如下: { "steps": [ {"step": 1, "action": "描述动作", "detail": "描述细节"} ] } """ def plan_task(user_goal): messages = [ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user_goal}, ] result = chat(messages) return json.loads(result)这里有一个小坑:模型输出偶尔会带前导空格、反引号甚至额外说明,直接json.loads会报错。我先不展开,后面章节会单独讲排查办法。新手可以先试试各种不同的任务描述,观察模型输出的结构稳定性,思考如何让自己的提示词更可靠。这一步练的不是代码,而是“调教模型输出结构”的直觉。
4.3 注册工具与模拟工具调用——核心中的核心
Agent与普通聊天机器人最大的区别,就是它能调用外部工具。这里我们不用框架,手工搭一个最简单的“工具注册表”。
TOOLS = { "get_current_time": { "desc": "获取当前时间,用于回答当前几点、日期等问题。", "func": lambda: "现在是2025年某个时间" # 实际可以返回真实时间 }, "calculate": { "desc": "用于数学计算,参数格式: expression, 例如 '1+2*3'", "func": lambda expr: str(eval(expr)) # 仅示例,生产环境绝对不能直接用eval } } def call_tool(name, args): if name in TOOLS: return TOOLS[name]["func"](**args) return "工具不存在"这个动手环节的意义在于,你会意识到“让模型调用工具”其实是一个协议问题:你要决定模型输出什么样的格式来表示它想调用哪个工具、传什么参数。框架里的工具调用机制本质上就是在帮你做这件事。如果你手工实现过一遍,后面用框架时看到那些工具装饰器、参数schema,就会豁然开朗。
4.4 一个完整的最小循环:先规划再执行的Demo
我们把上面的模块串起来,实现一个能“查询时间”和“做计算”的极简Agent。它的流程是:收到用户请求 → 交给模型 → 模型决定调用工具 → 程序执行工具 → 把结果返回给模型 → 模型给出最终回答。
TOOL_SYMBOLS = {name: TOOLS[name]["desc"] for name in TOOLS} SYSTEM_PROMPT_V2 = """ 你是智能助手。你可以使用以下工具: {tool_desc} 当需要工具时,只输出JSON: {"tool": "工具名", "args": {"参数名": "参数值"}} 当不需要工具时,直接输出回答文本。 你只能输出一样东西:要么是JSON,要么是文本。 """ def run_agent(user_input): messages = [ {"role": "system", "content": SYSTEM_PROMPT_V2.format(tool_desc=json.dumps(TOOL_SYMBOLS, ensure_ascii=False))}, {"role": "user", "content": user_input}, ] for i in range(5): # 最多循环5步 assistant_reply = chat(messages) messages.append({"role": "assistant", "content": assistant_reply}) try: action = json.loads(assistant_reply) except json.JSONDecodeError: # 不是JSON,视为最终回答 return assistant_reply if "tool" in action and "args" in action: result = call_tool(action["tool"], action["args"]) messages.append({ "role": "user", "content": f"工具结果:{result}。你可以继续,或直接给最终回答。" }) else: return assistant_reply return "已达到最大步骤限制,无法完成目标任务。"这个demo只有几十行,但已经具备了一个Agent的完整骨架。我强烈建议新手把这段代码敲一遍,哪怕不跑模型,先用纸笔画一下每一轮消息的变化,你都会对Agent的运行机制有非常直观的认识。
5. 练什么项目能快速积累经验——从简单到复杂的三层实践
5.1 第一层:输入输出格式化的小工具
纯调API并做结构化输出,不需要复杂逻辑。比如写一个“菜谱助手”,用户说“鸡蛋和西红柿”,模型输出JSON包含食材用量、步骤、预估时间。这个练习能强化你对JSON输出和提示词的掌控。
这类项目是最容易获得成就感的,因为两三小时就能跑通,而且可以无限换场景。我的经验是:练十个换皮的小工具,抵得上死磕一个大项目——因为变的是提示词,不变的是“模型输出结构化数据”的套路,这个套路练扎实了,Agent才谈得上下一步。
5.2 第二层:单工具调用的自动任务
比如给Agent接一个搜索接口,用户提问“帮我查一下某本书的作者”,Agent决定是否调用搜索、怎么填参数、怎么把结果组织成回答。这时你会开始体会到“模型的规划能力”带来的不确定性——同一个问题,可能会调用工具,也可能直接答非所问。
这个阶段不要急着加更多工具。先把一个工具调用的准确率提到90%以上,再考虑增加第二个工具。我见过很多人一上来就注册五个工具,结果模型经常选错,还找不到原因。其实问题往往出在工具描述写得不够清楚,或者测试用例不够典型。
5.3 第三层:多工具协作的复合任务
等到单工具调用稳定了,再加第二个、第三个工具,设计一个需要多次调用的任务。比如“根据用户指定的城市和日期,先查天气,再根据天气推荐穿衣搭配”。
这种任务的挑战在于模型可能不会按你预期的顺序调用工具,或者中间一步给出的参数不对。解决办法还是一样:先在提示词里明确步骤,用程序约束顺序;如果发现模型总是跳步,就要反思是不是工具描述或任务描述有歧义。
6. 实战中反复踩坑的高频问题,附排查思路
6.1 模型输出不是合法的JSON,怎么办
这是我遇到最多的问题。模型明明在提示词里被要求“只输出JSON”,结果返回了一段解释、多行代码块、或者用单引号代替双引号。
常规处理办法有这么几层:
- 在提示词里给“反面示例”:写明“不要输出markdown代码块,不要解释”;
- 解析时做容错:去掉字符串前后的```包裹,提取第一个{和最后一个}之间的内容;
- 让模型“自己修”:把解析失败的结果回传给模型,告诉它“刚才的输出无法解析,请只输出合法JSON”,再调用一次;
- 最省心的方案:如果接口支持结构化输出或JSON模式,直接开启,能在很大程度上规避这个问题。
我个人建议新手学一下“提取大括号内容”的容错函数,因为无论你以后用哪个厂家的接口,都还是需要自己处理边缘情况。
6.2 模型不调用工具,或者乱选工具
你可以先检查一下工具描述是不是不够明确。比如你有个“查天气”的工具,描述如果只写“获取天气”,模型经常搞不清参数怎么填;写清楚“根据城市名和日期获取未来3天天气预报,城市用中文全称”就明显好很多。
还有一个常见原因是系统提示词里没有强调“优先使用工具”。有些模型默认倾向直接用知识作答,这时候你要在提示词里加一句“涉及实时信息或计算时,必须调用工具”。多试几个说法,找到对你当前模型最有效的表达。
6.3 上下文丢失和Token超限
Agent跑了几轮之后,消息列表越来越长,可能出现两种后果:一是超出上下文窗口直接报错;二是模型把早期的指令“忘”了,因为早先的系统提示词被后续内容挤占了。
我的办法是:
- 循环每步之后检查消息总token数;
- 如果超过预设阈值,把最早的一轮对话压缩成摘要(用模型生成摘要),替换进消息列表;
- 每次循环都把最新的系统提示词重新注入,确保模型不会丢失行为基准。
这个“记忆管理”的概念,其实就是框架里高级功能的雏形,你提前踩过这个坑,后面看框架的memory模块会轻松很多。
6.4 跑循环时无限调用工具不结束
这是新手最容易卡住的问题:Agent在一个工具结果上反复做下一步规划,永远不给最终答案。要在设计循环时就加好护栏:
- 限制最大循环次数,比如5步或8步;
- 判断连续调用同一工具的频次,如果连续三次调用同一个工具,强行走人;
- 在消息里明确告诉模型“如果结果已经足够回答用户问题,直接输出最终答案”。
这些细节看起来很小,但决定了Agent在真实场景里能不能稳定用。
7. 关于“下一步”的个人经验与几个专用建议
我最近带新人时发现,最有效的学习曲线不是“从框架到原理”,而是“从原理到框架再回到原理”。我自己最早也是直接看框架,结果被各种抽象概念绕晕,花费了很多时间;后来老老实实用原生API把最小Agent写了一遍,才真正理解那些框架到底封装了什么。
所以如果让我给新手提几条具体的建议,我会说:
第一,先保证能在纯代码环境下写一个不依赖框架的循环Agent,哪怕只是上面那种几十行的demo。这个练习会让你建立对“模型-程序-工具”三方协作的直觉。
第二,提示词工程不要只学“怎么写得好”,更要学“怎么测试”,同一个功能准备十个测试用例,记录通过率,你才能量化自己的提示词改得好不好。
第三,结构化输出是Agent的地基,值得花最多时间打磨。宁可晚接触框架,也不要晚练JSON解析和错误兜底。
第四,学会记录Agent每一步的输入输出日志。调试的时候把消息列表完整打出来,你会很快发现问题出在“模型没理解”还是“工具返回异常”还是“解析逻辑有bug”。
这个领域迭代很快,今天很多热门工具可能很快被替代,但“让大模型遵循流程完成目标”的思路,以及“调API、解析输出、调用工具、管理上下文”的底层能力,会长期有效。把这四样练熟,再去挑框架,会是从容的观察者,而不是盲目的追风者。