1. 从"会聊天的模型"到"能办事的Agent":先厘清概念边界
很多人第一次接触 AI Agent 开发,脑子里其实是一团浆糊:大模型、LLM、Agent、AI 模型,这几个词天天在热搜上滚,但到底谁是谁、谁包含谁,说不清楚。我见过不少简历上写着"熟悉 Agent 开发"的人,聊两句就露馅——把调用一次 API 返回一段文本当成了 Agent。所以这篇东西我不打算从"什么是人工智能"讲起,而是直接从工程视角把概念切干净,再往下讲怎么搭、怎么调、怎么避坑。
先把最容易被混淆的一组关系摆出来。大模型是个宽泛的统称,指参数规模大、经过海量数据训练的神经网络模型,它可以是纯文本的,也可以是多模态的(能看图、听声音)。LLM(Large Language Model)是大模型里的一个子集,专指语言模型这一类。而大家常挂在嘴边的 DeepSeek、Qwen、GPT 系列、Claude 系列,都属于具体的 LLM 产品/模型权重。至于AI Agent,它不是模型,而是一套以 LLM 为推理内核、能自主规划并调用工具去完成目标的软件系统。一句话概括:LLM 是大脑,Agent 是"大脑 + 手脚 + 记忆 + 工作流程"。
这个区分为什么重要?因为它直接决定了你开发时的工作重心。如果你做的是纯 LLM 应用,比如一个文案润色工具,你的核心工作是提示词工程——把指令写清楚,把输出格式约束好。但如果你做的是 Agent,提示词只是其中一环,你还要处理工具定义、任务拆解、状态管理、错误重试、上下文裁剪这一整套工程问题。我个人的经验是,一个能跑通的 Agent 项目里,提示词相关的工作量大概只占三成,剩下七成全是围绕"怎么让模型稳定地做出正确决策并正确调用工具"。
再补一个常被问到的点:Agent 和普通"套壳聊天"的本质差别在哪?差别在于控制流的归属。普通聊天应用里,控制流在你手里——用户输入,你拼提示词,调模型,拿结果,结束。而在 Agent 里,控制流部分交给了模型:模型自己决定要不要调用工具、调用哪个、调用几次、什么时候停下来。这就带来一个工程上的核心矛盾——你既要给模型足够的自由度去应对复杂任务,又要给它足够的约束防止它跑飞。后面几节讲的几乎所有技巧,本质上都是在平衡这两者。
理解了这层,你再看那些热搜词——"agent 和 llm 和 ai 模型有什么区别"、"agent 开发需要哪些技术栈"——就不会觉得是零散的知识点了,它们其实是同一个认知框架下的不同切面。
2. Agent 的骨架:把"自主性"拆成可实现的四个部件
2.1 推理内核与它的能力边界
推理内核就是那个 LLM。选型时很多人一上来就问"哪个模型最强",这其实是个伪命题,因为 Agent 场景下你要看的不是通用榜单分数,而是三个具体指标:指令遵循能力、工具调用(Function Calling)的稳定性、以及长上下文下的注意力保持。我踩过的坑是:某个模型在聊天里表现惊艳,但一让它按 JSON schema 输出工具调用参数就开始漏字段、加解释性文字,导致解析失败。这种模型再"聪明"也不适合做 Agent 内核。
关于本地部署,热搜里"ollama 本地部署大模型哪个模型最佳"、"rx6750gre 训练大模型"这类问题特别多。我的建议很直接:本地部署优先用于开发和隐私敏感场景,生产环境要慎重。7B 级别的模型(比如 Qwen2.5-7B)在消费级显卡上跑推理是可行的,但工具调用的稳定性明显不如更大的模型。如果你只是学习 Agent 开发流程,本地跑一个 7B 模型完全够用;但如果你要做真正能上线的 Agent,模型能力的天花板会直接决定你 Agent 的可靠性上限。
2.2 工具层:Agent 的"手脚"怎么定义
工具就是 Agent 能调用的外部函数。它可以是查数据库、调 API、读文件、执行计算、发消息。定义工具时有个反直觉的经验:工具的描述文字比工具本身的实现更影响成功率。模型是靠读你的工具描述来决定调不调的,描述写得含糊,模型就会乱调或者不调。
一个合格的工具有四个要素:名称(语义清晰、动词开头)、描述(说明什么时候用、什么时候不用)、参数 schema(类型、必填项、取值范围)、返回值约定(成功和失败分别返回什么结构)。我见过太多人参数 schema 写得极其宽松,全是 string 类型,结果模型传进来的东西五花八门,后端解析直接崩。参数类型能收紧就收紧,枚举值能列全就列全,这是省下大量调试时间的笨办法,但极其有效。
2.3 记忆:短期上下文与长期存储的分工
Agent 的"记忆"分两层。短期记忆就是当前对话的上下文窗口,它决定了 Agent 能"记住"多久之前的事。长期记忆则是外部的向量库或结构化存储,用来跨会话保留信息。热搜里"ai agent skill memory mcp"提到的 memory,说的就是这套机制。
这里有个关键工程决策:不是所有历史都要塞进上下文。上下文越长,成本越高、延迟越大,而且模型在超长上下文里反而容易"迷失"。我的做法是分层处理——最近几轮对话原样保留,更早的对话做摘要压缩,重要事实(用户偏好、已确认的结论)抽出来存进长期记忆,需要时再检索回来。这套"上下文工程"的思路,其实是提示词工程的延伸:提示词工程管的是"这一次怎么问",上下文工程管的是"这一轮该带哪些信息进来"。
2.4 编排循环:让 Agent 真正"跑起来"
编排循环是 Agent 的心脏。最基础的形态是 ReAct 模式:模型思考(Reason)→ 决定行动(Act)→ 观察结果(Observe)→ 再思考,循环直到任务完成或达到终止条件。听起来简单,但工程上有几个必须处理的点。
第一是终止条件。必须有最大步数限制,否则模型可能陷入死循环,反复调用同一个工具。第二是错误处理。工具调用失败时,要把错误信息结构化地喂回给模型,让它有机会换策略,而不是直接崩掉。第三是中间状态的可观测性。Agent 跑起来后你得像看日志一样能看到它每一步在想什么、调了什么、拿到了什么,否则出了问题根本无从下手。我强烈建议在开发阶段把每一步的推理和工具调用都打印出来,这个习惯能帮你省下无数排查时间。
3. 提示词工程在 Agent 里的真实位置
3.1 系统提示词决定了 Agent 的"人格"和"纪律"
在 Agent 里,系统提示词不是可有可无的开场白,它是行为规范。它要回答几个问题:你是什么角色、你的目标是什么、你能用哪些工具、遇到不确定时该怎么办、绝对不能做什么。我写系统提示词有个习惯,把它当成给一个新员工的入职手册来写——具体、可执行、有边界。
一个常见的错误是把系统提示词写得太"客气"。"你是一个乐于助人的助手,请尽力帮助用户"这种话对 Agent 几乎没用。有效的写法是给出明确的决策规则,比如"当用户询问实时数据时,必须先调用查询工具,不得凭记忆回答"、"如果工具返回空结果,最多重试一次,然后如实告知用户"。规则要具体到可判定,模型才能稳定执行。
3.2 少样本示例比长篇描述更管用
与其用一大段文字描述"你应该怎么调用工具",不如直接给两三个完整的调用示例。模型对示例的模仿能力远强于对抽象规则的理解能力。我通常会在系统提示词里放一组"输入 → 思考 → 工具调用 → 输出"的完整样例,覆盖最典型的场景。实测下来,加了示例之后工具调用的格式错误率能降一大截。
但示例也不是越多越好。示例太多会挤占上下文,还可能让模型过度拟合到示例的具体形式。我的经验是三到五个高质量示例是甜点区,覆盖正常路径、边界情况和错误处理各一个。
3.3 输出格式约束:让下游能解析
Agent 的输出往往要被程序解析,所以格式约束是刚需。最稳的做法是优先用模型原生的结构化输出能力(比如 Function Calling 或 JSON mode),而不是靠提示词里写"请输出 JSON"。因为前者是模型层面强约束的,后者只是"请求",模型心情不好就可能给你加个"好的,以下是结果:"的前缀,解析直接失败。
如果不得不用提示词约束格式,那就在提示词里把 schema 写死,并明确"只输出 JSON,不要任何其他文字"。同时后端解析一定要做容错——去掉可能的 markdown 代码块标记、处理前后空白、对解析失败做重试。永远不要假设模型会 100% 遵守格式,这是我在生产环境里用血换来的教训。
4. 开发框架怎么选:别被"框架"两个字绑架
4.1 先问自己需不需要框架
热搜里"agent 开发需要哪些技术栈"、"java+ee+开发框架"、"node 开发 flow agent"这类问题背后,藏着一个默认假设:做 Agent 必须用某个框架。我的观点是——简单的 Agent 用原生代码 + SDK 就够了,框架是等你被复杂度逼到墙角时才引入的。
一个只有两三个工具、单轮任务、不需要复杂记忆的 Agent,你用几十行代码直接调模型 API 就能实现,引入框架反而增加了一层你不理解的抽象,出问题时排查成本更高。什么时候该上框架?当你的 Agent 需要多步规划、多工具协同、状态持久化、多 Agent 协作时,框架提供的编排、状态管理、可观测性能力才开始值回票价。
4.2 主流框架的取舍逻辑
市面上的 Agent 框架大致分几类。一类是通用编排框架,提供 Agent 循环、工具注册、记忆管理等抽象,适合快速搭原型。一类是图/工作流框架,把 Agent 的执行过程建模成有向图,节点是步骤、边是转移条件,适合流程明确、需要精细控制的场景。还有一类是轻量 SDK,只提供模型调用和工具调用的基础封装,把编排逻辑留给你自己写。
选型的核心问题是:你的任务流程是"确定"的还是"涌现"的?如果流程基本固定(比如先查数据、再分析、再生成报告),用工作流框架把流程画出来,可控性最高。如果任务高度开放(比如一个能处理各种用户请求的通用助手),那就需要更自由的 Agent 循环,让模型自己决定路径。我个人的偏好是:能用确定性代码写死的部分,绝不交给模型决策。模型只负责它真正擅长的——理解模糊意图、做非结构化判断。
4.3 技术栈的现实考量
语言层面,Python 生态最成熟,几乎所有模型 SDK 和 Agent 框架都优先支持 Python,做原型和实验首选。但如果你的 Agent 要嵌入已有的 Java 或 Node 后端系统,那就得权衡——是让 Agent 作为独立服务用 Python 写、通过 HTTP 对接,还是用对应语言的 SDK 硬写。我的建议是Agent 服务独立部署,用最顺手的语言写,通过清晰的接口和主系统解耦。这样模型迭代、框架升级都不会牵动主系统。
5. 从零搭一个能用的 Agent:完整实操链路
5.1 环境准备与最小可运行版本
先搭一个最小闭环,别一上来就追求功能齐全。最小版本包含:一个模型调用封装、一个工具注册机制、一个 ReAct 循环、一个命令行交互入口。这个版本可能只有一两百行代码,但它能让你把整条链路跑通,理解数据是怎么流动的。
环境上,Python 项目建议用虚拟环境隔离依赖,模型调用优先用官方 SDK。如果你用本地模型,Ollama 这类工具能让你用统一接口调用本地模型,开发阶段切换模型很方便。关键是把模型调用抽象成一个函数,输入是消息列表和工具定义,输出是模型回复,这样换模型时只改这一处。
5.2 工具注册与调用的实现细节
工具注册我推荐用一个装饰器或注册表模式,把函数和它的 schema 绑定在一起。每个工具函数要处理三件事:参数校验(防止模型传错类型)、异常捕获(工具内部报错不能直接抛出,要转成结构化错误返回给模型)、返回值序列化(统一成模型能理解的格式)。
调用环节最容易出问题的是参数解析。模型返回的工具调用参数可能是 JSON 字符串,也可能已经是对象,不同 SDK 行为不一致。一定要写健壮的解析逻辑,解析失败时把原始内容记进日志,方便定位是模型的问题还是解析的问题。
5.3 循环控制与终止策略
循环控制要设三道闸。第一道是最大迭代次数,防止无限循环。第二道是重复调用检测,如果模型连续用相同参数调用同一个工具,说明它卡住了,应该中断并报错。第三道是超时控制,整个任务设一个总时长上限,避免某个工具卡死拖垮整个请求。
终止策略上,除了"任务完成"这个正常终止,还要处理"模型认为无法完成"的情况。要让模型有能力说"我做不到",而不是硬编一个答案。这需要在系统提示词里明确告诉它:当信息不足或工具无法解决问题时,如实说明,不要编造。
5.4 可观测性:开发阶段的生命线
前面提过,但值得单独强调。开发阶段一定要把每一步的完整信息打出来:模型的思考内容、决定调用的工具和参数、工具返回的结果、下一步的决策。最好能把这些结构化存储,方便回放和分析。我习惯给每次 Agent 运行生成一个 trace id,所有日志带上这个 id,排查问题时能完整还原一次执行过程。这个投入在项目变复杂后回报巨大。
6. 那些文档不会告诉你的坑
6.1 工具描述写得太"聪明"反而坏事
新手容易把工具描述写得又长又全,恨不得把所有可能性都列上。结果模型读完反而抓不住重点,该调的时候犹豫,不该调的时候乱调。我的经验是工具描述要短、要聚焦在"什么时候用",实现细节不用写进去。一个工具只干一件事,职责单一,模型判断起来才准。
6.2 上下文不是越多越好
很多人觉得把历史对话全塞进去,模型就能"记住"一切。实际上上下文越长,模型越容易忽略中间部分的信息(所谓的"lost in the middle"现象),而且成本和延迟都上去了。正确的做法是主动管理上下文:该压缩的压缩,该丢弃的丢弃,该检索的检索。把最相关的信息放在上下文的开头和结尾,中间放次要信息。
6.3 别指望模型自己"学会"你的业务规则
模型不知道你的业务细节,你不告诉它,它就会按通用常识瞎猜。所有业务规则、边界条件、特殊处理,都必须显式写进系统提示词或工具描述里。我见过有人抱怨"模型怎么连这个都不懂",一问才知道规则压根没写进去。模型不会读心,它只会读你给它的文字。
6.4 错误处理要"喂回"给模型
工具调用失败时,直接把异常抛给用户是最差的做法。正确姿势是把错误信息结构化后喂回给模型,让它有机会调整策略。比如查询超时了,告诉模型"查询超时,可以尝试缩小查询范围或稍后重试",模型往往能自己找到替代方案。这个机制能显著提升 Agent 的鲁棒性。
6.5 测试要覆盖"模型不听话"的情况
普通软件的测试是确定性的,输入 A 必然得到 B。Agent 的测试是概率性的,同样的输入可能得到不同结果。所以测试策略要变:重点测边界和异常路径,比如工具返回空、工具报错、模型输出格式错误、模型陷入循环。这些"不听话"的情况才是 Agent 真正容易崩的地方。我通常会给每个工具写 mock,模拟各种异常返回,然后观察 Agent 能不能优雅处理。
7. 学习路线与进阶方向
7.1 一条务实的入门路径
如果你现在完全零基础,我建议的顺序是:先花时间把 LLM 的基本调用跑通,理解消息角色、上下文、token 这些概念;然后写一个最简单的工具调用示例,理解 Function Calling 的机制;接着手写一个 ReAct 循环,不借助任何框架;最后再引入框架,对比框架帮你省了哪些事。这个顺序的好处是,你先把底层机制摸透了,用框架时才不会"知其然不知其所以然"。
热搜里"ai agent 入门教程"、"agent 开发学习路线"这类内容很多,但大部分要么太浅(只讲概念),要么太跳(直接上框架)。我建议你以动手为主,每学一个概念就写代码验证。Agent 开发是门实践性极强的活,看十篇教程不如自己踩一个坑。
7.2 面试和进阶该准备什么
如果你在准备 Agent 开发岗的面试,高频考点集中在几块:Function Calling 的原理和实现、ReAct 等 Agent 范式的区别、上下文管理策略、多 Agent 协作的架构、以及如何评估 Agent 的效果。评估这块特别容易被忽略——你怎么知道你的 Agent 变好了?需要有一套评测集和指标,比如任务完成率、工具调用准确率、平均步数、失败原因分布。能讲清楚怎么评测的人,在面试里会明显加分。
进阶方向上,多模态 Agent(能处理图像、语音)、多 Agent 协作(多个 Agent 分工完成复杂任务)、以及 Agent 的自动化运维(比如用 Agent 做系统巡检)都是当前比较热的方向。但我的建议是先把单 Agent 做扎实,多 Agent 的复杂度是指数级上升的,单 Agent 都没搞明白就上多 Agent,基本是给自己找罪受。
7.3 关于"要不要学微调"
热搜里"大模型微调"、"qwen2.5-7b 微调行业大模型"这类内容热度很高。我的看法是:对绝大多数 Agent 开发场景,微调不是第一优先级。先把提示词工程、工具设计、上下文管理做好,能解决八成问题。微调适合的是那些有大量领域数据、且通用模型确实无法通过提示词达到效果的场景。而且微调有维护成本——模型更新了、数据变了,你可能要重新调。所以除非你确认提示词路线走不通,否则别急着上微调。
8. 我踩过的几个真实坑
说几个具体的。第一个是工具返回值太大。有次我让 Agent 查数据库,工具直接把几万行结果返回了,塞进上下文后模型直接"懵"了,后续推理全乱。后来改成工具内部先做聚合和截断,只返回摘要和关键字段,问题立刻解决。工具返回给模型的数据要精炼,不是越多越好。
第二个是模型对工具名的理解偏差。我有个工具叫search,本意是搜内部知识库,但模型经常把它当成"上网搜索"来用,参数传得乱七八糟。后来把名字改成search_internal_knowledge_base,描述里明确写"仅用于查询公司内部文档,不用于互联网搜索",误用率大幅下降。工具命名要带上下文,别用太通用的词。
第三个是并发场景下的状态污染。早期我把对话历史存在全局变量里,单用户测试没问题,一上并发就串了。后来改成每个会话独立的状态对象,用会话 id 隔离,才彻底解决。Agent 的状态管理一定要按会话隔离,这是基本纪律。
第四个是过度依赖模型的"常识"。有次让 Agent 处理日期,我以为模型肯定知道"下周三"是哪天,结果它算错了。后来我在系统提示词里注入了当前日期,并明确要求所有日期计算必须调用日期工具,不再依赖模型心算。凡是涉及精确计算、实时信息、业务规则的,一律走工具,别信模型的"记忆"。
9. 关于工具链和生态的一点个人看法
现在 Agent 相关的工具和框架更新极快,今天学的 API 明天可能就变了。面对这种快速变化,我的应对策略是抓住不变的东西:Agent 的核心循环(思考-行动-观察)、工具调用的本质(结构化地让模型触发外部函数)、上下文管理的目标(在有限窗口里放最相关的信息)。这些是不随框架更迭而改变的底层逻辑。框架只是这些逻辑的不同实现方式,理解了底层,换框架就是换个写法而已。
另外,别盲目追新。看到一个新框架就冲上去用,结果项目里堆了一堆半生不熟的依赖,维护起来苦不堪言。我的原则是:生产项目用成熟稳定的方案,个人学习可以大胆试新。把新东西在玩具项目里玩透了,确认靠谱再往正式项目里引。
最后分享一个我自己的习惯:每做完一个 Agent 项目,我都会把这次遇到的坑、用到的技巧、以及"下次一定不这么干"的地方记下来。Agent 开发这行,经验基本都是从坑里爬出来的,文档能教你的有限,真正让你进步的是那些让你熬夜排查的诡异问题。把这些记下来,下次遇到类似场景,你就能少走一大截弯路。