简介李飞飞团队主导撰写的AI Agent综述PDF围绕智能体原理、系统架构与多模态交互面向人工智能研究者、算法工程师和对通用人工智能AGI感兴趣的进阶学习者。文章明确定义“Agent AI”这一交互式AI类别系统介绍如何利用生成式AI与多个独立数据源开展现实无关训练并阐述具身代理在物理与虚拟环境中感知视觉、音频、场景情感等信息、产生有意义动作的路径同时指出将智能体嵌入真实或模拟环境有助于缓解大型基础模型产生不符合环境事实的幻觉。资源为1个PDF文件压缩包约50.51MB便于离线精读。已有6459人学习下载适合作为AI Agent方向综述入门、论文引读或研究选题的第一手资料可帮助读者快速建立多模态智能体的整体认知框架并了解斯坦福、微软等机构在该领域的最新系统化观察。1. 李飞飞的AI Agent综述AI Agent不是更聪明的对话框斯坦福李飞飞团队2024年公开的AI Agent综述被从业者当成一张给Agent正名的学术地图它把市面上吵了半年的“什么才算Agent”第一次收敛成学术定义——一个有记忆、规划、工具、行动四要素的闭环系统外部必须带环境行动改变环境环境反过来改写记忆。媒体管李飞飞叫“人工智能之母”这份综述的含金量在于它拒绝把Agent解释成“更强的对话框”。这篇笔记不替你复述论文而是拿这套框架陪你走一遍落地路径怎么理解理论、怎么搭一个FastAPILangGraph的最小Agent、并发怎么扛、评测怎么做以及这个方向到底值不值得投入。2. 搭建AI Agent前先理解综述里的架构三角记忆、规划、工具怎么逼你重构项目2.1 从“提示词工程”到“Agent系统”综述判定的关键转折过去两年“提示词工程”解决的是把模型的单次输出调对李飞飞团队的综述想纠正的是另一件事当AI Agent的动作会实际改变一个系统时模型的单次文本输出已经不足以定义Agent行为了。动作改变环境环境刷新记忆记忆又参与下一次规划。综述把这套循环归纳成四个要素记忆、规划、工具、行动我在实践中更愿意在四要素外面再套一层“环境”因为缺少环境这个参照系记忆和行动都会失去锚点。这里的判断标准其实非常朴实你的系统除了生成文本有没有改变外部世界比如写入文件、调用业务API、下单、发消息有没有在下一次决策时把外部结果读回来如果都没有那无论接了多少个工具它都还是一个“聊天机器人加插件”不是Agent。维度对话机器人AI Agent按综述定义核心循环输入→模型→输出感知→规划→行动→环境反馈→记忆更新→再规划记忆对话上下文对环境状态的结构化表征工具可选插件行动的必要环节副作用必须有记录失败处理重新生成一次回滚 / 重试 / 人工接管这个表格不是文字游戏。团队里最常出现的分歧是“这个项目到底要不要按Agent来做”用这张表对一下就能收敛只要存在“行动会失败、环境会变化、记忆要更新”这三个特征就必须按Agent架构设计否则后续一定会为了补丁打补丁。2.2 理论落地的三种常见选型LangGraph、Rust、硬编码按综述四要素落地常见做法有三类我按团队实际情况做了一个选型对照表选型适合场景与综述框架的对应关系上手成本LangGraphPython技术栈、需要图编排、人工审核、断点续跑记忆State规划节点循环行动工具节点中等基于Rust的AI Agent实现对延迟和并发极其敏感调度层自己握行动/状态同步、限流都在服务层做不占模型上下文高裸LangChain链快速Demo、内部工具控制流弱容易退化成“对话动作”低很多人把LangGraph当成LangChain的升级版其实它真正对应综述里的“规划”这个动作图里的每个节点是一个决策点每条边是一次有条件的状态跳转循环由边的条件控制而不是由代码里的while控制。这个差别后面写代码时会体现得很明显。选型定了之后我一般会先做一件事把“任务完成率”定义出来。综述里反复强调随机初始条件与多模型对比翻译成团队语言就是准备20个不同的用户目标每个跑3遍统计在预定步数内完成任务的次数同时记录总token成本。没有这个基线后续任何bug修复都是盲改这是血泪经验。基于Rust的AI Agent在校验这类指标时也不错它适合把上层的编排和推理调度做成低延迟服务不过多数团队用LangGraph的ROI更高。如果团队已经被Spring全家桶绑定spring ai agent也可以纳入考虑但它的循环控制和人工审核内置较弱我一般只把它当“工具执行器”来用真正的规划还是交给一张显式的状态图。2.3 用这套框架改掉“伪Agent”从天气聊天到自动化发布先给一个极具欺骗性的伪Agent长得很像Agent实际只是循环调用模型# 伪Agent只有“输入→模型→输出”这一层循环 def fake_agent(user_query: str): while True: response llm.chat(user_query) print(response) if 结束 in response: break逻辑说明这段代码没有任何一步改变外部环境也从不把环境状态读回记忆它唯一的能力是不断生成文本。按综述的定义它只能算“带循环的聊天机器人”。改成真正的Agent需要引入两个新节点ToolCall节点负责执行工具或写入数据StateUpdate节点把执行结果同步回State形成闭环。# Agent化的核心行动改变状态状态参与下一步规划 def real_agent(state: dict) - dict: # 第一步规划。读状态决定下一步动作 plan planner.invoke({memory: state[memory], goal: state[goal]}) # 第二步行动。真正调用外部工具例如发布接口 result tool.invoke({tool: plan[tool_name], args: plan[args]}) # 第三步记忆更新。把外部结果写回而不是只追加一句对话 state[memory].append({tool_result: result}) state[environment] sync_environment(result) return state参数说明planner的temperature建议调到0.1~0.3保证工具名与参数格式稳定tool.invoke必须设置超时requests默认5秒左右比较常见读写的接口超时太长会拖垮整个Agent循环sync_environment这一步最容易被省略省略之后的症状就是Agent第二次决策时“失忆”。这点在很多自动化场景里都会被验证。比如“AI Agent让小红书自动发消息”拆成综述框架就是文案生成是规划调用发布API是行动发布结果是否成功是环境反馈下次要不要重发看反馈有没有写回记忆。看起来是模型写文案真正难点其实在状态同步和重试边界。想让AI Agent真的下地干活这些步骤一个都不能少。3. 常见问题里的代价课环境、规划、记忆三个假设哪里最容易翻车综述给了理论框架但论文里的Agent跑在受控的模拟环境里生产环境不是。综述里还有一个被忽略的方法论点所有随机初始状态下的结果都要记录只报成功案例就是自欺欺人。落到项目上这句话直接规定了下述三个坑的排查方式——环境、规划、记忆是最容易翻车的三个假设。3.1 环境假设把测试环境当生产环境第一天上线就被打脸现象让Agent代替运营处理工单。测试环境里Agent能准确读取工单、调用模板、关闭工单演示非常顺利。一上生产开始回复错人、状态没同步、工单被重复关闭。原因测试环境是封闭模拟器工单列表是静态数据生产工单是开放系统用户可能正通过其他渠道改单Agent读取和行动之间状态已经变了。综述里强调“行动必须产生环境变化”但在生产环境里“行动基于的环境版本是否还成立”必须先确认。解决给环境的读写操作都包一层版本号或时间戳。行动前先核对环境版本不一致就放弃操作、重新读取再决定下一步。敢让Agent直接对公网系统做写操作之前先跑至少两周“只读观察影子模式”把环境变化频率摸清楚。所谓影子模式就是把生产流量用镜像复制一份给AgentAgent只做决策和记录不真正执行写操作两周后对比它打算做的事和人工实际做的事一致率超过95%再放开写权限。这个“先核对再行动”的措施能拦掉一半同类故障。3.2 规划假设把几步推理当成长期规划token成本直接翻倍现象Agent做商品导购时陷入比价循环调A接口、调B接口、确认库存、再调A接口十几个来回停不下来。原因是目标模糊时模型会倾向于“再探索一步”尤其在各家接口返回的数据不完全一致时它总觉得还有一步就能找到最优解。原因综述讨论的规划是“有限步数内通过反馈逼近目标”不是开放世界里的自由探索。开放世界里最优目标本身就会漂移不给步数上限token成本是小事失控才是大事。解决给每条任务线设定硬性步数上限比如8步在同一工具连续调用两次且没有产生状态变化时强制转入人工兜底。这个规则必须是纯规则代码别指望通过改提示词让模型自己控制模型没有“成本意识”。设置上限时可以做个简单换算记录当前Agent每步平均消耗token乘以上限就是单任务最坏成本用这个值反推上限定多少合适。比如单步平均450token8步就是3600token按当前模型价格折算下来能接受那上限就定8步不能再多。3.3 记忆假设只存对话摘要不存环境状态Agent永远记不住现象用户在第1轮告诉Agent“我喜欢无糖、少冰”第5轮它就忘光了但对话记录里明明有这句话。原因按综述的理解记忆是对环境状态的重新表征对话历史上的文本只是原始日志不是记忆。把“对话摘要”当成记忆存进去每次推理都要重新猜测这些偏好到底约束当前什么行为模型上下文再大也扛不住这种隐式推理。解决把记忆拆成三层。事实记忆存用户偏好状态记忆存购物车、订单、草稿这类可变数据技能记忆存某类任务的处理流程在State里用固定的字段分别存不要全部堆进messages数组。实际落地时State里大概是三个字段facts里存“无糖、少冰”这类长期偏好status里存“当前购物车有三件商品、订单已提交”这类易变数据skills里存“处理退款先查订单再调接口”这类流程知识。这样“第5轮失忆”的问题根本不依赖模型的上下文窗口。这三条坑有个共同点都不是模型能力问题而是工程里“环境一致性”出了问题。所以排查顺序也固定先看环境同步再看步数限制最后看记忆结构。按这个顺序排查通常不用动模型就能解决大部分故障。4. 从综述到可运行代码用FastAPILangGraph搭一个最小AI Agent4.1 为什么选LangGraph而不是裸LangChain节点图对应“规划”闭环先说结论LangGraph不是赶时髦的新框架它的有向图结构刚好对应综述里的Agent循环。LangChain解决了“把工具接到模型上”这件事但它是链式结构节点之间不支持带条件的循环而Agent恰恰是“规划→行动→看反馈→再规划”的循环。LangGraph在LangChain基础上引入了StateGraph。State是贯穿流程的共享状态边可以做条件跳转节点可以暂停等待人工输入这些能力对应综述里的“规划”和“行动”两个动作。模型每次只代理一个决策节点外部工具状态由代码管这也是让Agent行为可解释的关键。配合FastAPI是因为技术栈的异步优势FastAPI的async接口和LangGraph的Async API天然对味。团队如果已经用django搭过一套后台也不是不能用但Agent编排里的“同步阻塞”问题会逼你额外引入Celery这套重武器收益不大。用FastAPI LangGraph每个请求进来是一个独立thread_id状态天然隔离这是后续并发的基础。4.2 最小Agent代码骨架记忆、规划、工具、行动一次跑通下面是一份最小的Agent骨架覆盖综述四要素from typing import TypedDict from langgraph.graph import StateGraph, END from langchain_openai import ChatOpenAI from langchain_core.tools import tool # AgentState把记忆、工具参数、行动结果都放进状态里 class AgentState(TypedDict): conversation: list # 原始对话记录 memory: dict # 结构化记忆事实/状态/技能 pending_tool: str # 本次规划决定的工具名 pending_args: dict # 本次规划决定的工具参数 tool def post_publish(content: str) - dict: 发布内容到业务系统返回发布状态。 # 真实环境这里换成 httpx.AsyncClient 调业务API resp business_api.post(/api/publish, json{content: content}) return {status: resp.status_code, message_id: resp.json().get(id)} # 规划节点基于记忆与目标决定下一个动作 async def planner(state: AgentState) - AgentState: prompt ( f目标{state[memory].get(goal)}\n f最近记录{state[conversation][-3:]}\n 只输出工具名和参数JSON不要解释。 ) llm ChatOpenAI(modelgpt-4o-mini, temperature0.1) # decision 已通过 with_structured_output 解析成 dict decision await llm.ainvoke(prompt) state[pending_tool] decision.get(tool, post_publish) state[pending_args] decision.get(args, {content: 默认文案}) return state # 行动节点执行工具把结果写回记忆 async def actor(state: AgentState) - AgentState: result post_publish.invoke(state[pending_args]) state[memory][last_action_result] result state[conversation].append({tool: state[pending_tool], result: result}) return state # 状态图节点之间有条件的循环 graph StateGraph(AgentState) graph.add_node(planner, planner) graph.add_node(actor, actor) graph.add_edge(planner, actor) graph.add_conditional_edges(actor, lambda s: planner if not s[memory].get(done) else END) app graph.compile() result await app.ainvoke({ conversation: [], memory: {goal: 把这篇摘要发布到公众号}, }) print(result)逻辑说明整个图只有两个节点循环靠图里的条件边实现。planner产出决策actor执行发布并回写memoryactor结束时如果memory里没有done标记就无条件回到planner继续规划直到某个节点把done置为True。这个结构对应综述里的“规划-行动-反馈”闭环。参数说明temperature0.1是为了让工具名和参数格式保持稳定模型选gpt-4o-mini这一级别的就够做决策把更贵的模型留给正文生成和总结是成本拆分的第一步post_publish里的business_api.post是示意生产环境建议换成异步HTTP客户端并设置3秒超时done标记的真正来源是工具执行后的返回值示例里为了简洁没有在actor里判定真实项目应该在actor节点里根据返回值判断done并更新memory。另外LangGraph自带checkpointer我给每个Agent任务传一个thread_id就可以断点续跑。这个能力对应“任务被中断后恢复”对长任务格外值钱社区讨论里经常被忽略。提示LangGraph的thread_id一旦切换checkpointer会读不到旧状态。生产环境里一个任务一个thread_id不要复用否则断点续跑会跳到错误的任务上。4.3 参数速查temperature、max_tokens、recursion_limit与第一个并发参数Agent类任务和普通Chat任务的参数策略很不一样先把最常调的参数列出来参数建议值作用temperature0.1~0.3决定工具名和参数格式的稳定性max_tokens50~200压缩决策输出降低解析失败率recursion_limit8~12给Agent循环加硬上限防止失控工具超时3~5秒外部接口慢不能拖垮整个Agentthread_id每次任务唯一隔离Agent实例状态断点续跑的基础第一次面对“AI Agent怎么扛并发”时别急着给模型服务加机器。问题通常出在状态上多个Agent实例共用同一个State对象调用工具时参数就会串。给每个任务独立thread_id是LangGraph里并发安全的第一步。至于真正的并发限流和背压放到下一章。5. AI Agent怎么扛并发与三层评测从“演示级”到“可交付”的分水岭5.1 “AI Agent怎么扛并发”的本质不是给LLM加机器是给状态加锁“AI Agent怎么扛并发”是最近问得最多的问题。我的回答基本固定Agent的瓶颈不在模型API而在状态。并发量上来后多个任务会同时读写同一个memory、同一个session甚至同一个外部业务账号。举个例子让AI Agent自动在社交平台上定时发布。10个任务并发时“草稿”和“已发布”状态在队列里互相污染导致发布内容串号、重复发送。按综述的理解多个Agent共享同一个环境时要给环境访问加锁或加事务不能指望LLM自己避开并行冲突。这类问题要用正交的服务层解决而不是调模型参数。先把状态锁做对再去碰模型参数那些玄学顺序别反。如果团队有人坚持用Rust做Agent调度层我理解他的动机Rust在并发状态隔离上有天然优势线程安全的共享状态比Python里四处飞的全局dict可靠得多。但对多数团队来说PythonLangGraph独立thread_id的组合已经把90%的状态冲突挡住了剩下的是业务级的锁和限流不值得为了那10%重写一套服务。5.2 用asyncio.Semaphore做并发控制代码与背压逻辑FastAPILangGraph的组合里最简单的并发控制是asyncio信号量from asyncio import Semaphore from uuid import uuid4 from fastapi import FastAPI, BackgroundTasks app FastAPI() agent_sem Semaphore(5) # 同时最多跑5个Agent实例 async def run_agent_task(user_input: str, thread_id: str): async with agent_sem: config { recursion_limit: 8, configurable: {thread_id: thread_id}, } result await agent_graph.ainvoke( {conversation: [], memory: {goal: user_input}}, config ) return result app.post(/agent/task) async def create_task(user_input: str, background_tasks: BackgroundTasks): thread_id uuid4().hex background_tasks.add_task(run_agent_task, user_input, thread_id) # 先返回任务号让客户端轮询而不是傻等3分钟 return {task_id: thread_id, status: queued}逻辑说明信号量限制的是“同时执行的Agent实例数”不是HTTP请求数。FastAPI的BackgroundTasks让请求快速返回重活交给后台进程客户端轮询任务状态。这个设计就是“背压”并发超限时任务排队等待而不是让Agent强行超跑触发模型API的429限流。参数说明Semaphore(5)要根据模型配额算不是随手定的。比如模型每分钟允许2万token单任务平均消耗4000token5并发刚好卡在配额附近如果配额更低信号量调小到3或4。任务如果分两个阶段比如“规划”阶段短token、“生成长文”阶段大token就分别定义plan_sem和gen_sem两个信号量避免一个长任务占住全局并发额度。5.3 三层评测方案单步对拍、全程回放、线上观测综述里最值得工程化的部分是它坚持的评测方法论面向任务的场景、随机初始条件、多个模型对比。落到团队执行我给项目定的三层评测是这样第一层单步对拍。固定一批决策输入让Agent只输出“工具名参数”用规则比对预期输出。这层跑得最快适合放CI每次提交都跑拦的是工具格式错误和参数字段丢失。第二层全程回放。录制一段真实用户请求脱敏后用同一个Agent版本重放对比旧版本和新版本的任务完成率。由于LLM输出有随机性同一个请求要跑3遍取中位数再比。完成率的定义要提前冻结成功走到终点的次数除以总请求数。第三层线上观测。不仅记录Agent最终结果还记录状态变化序列每一步读了什么、写了什么、调用哪个工具、返回什么。这个序列进日志系统后每次出问题都可以精准定位到第几步而不是对着“Agent回答错了”空猜。三层成本逐步增加。第一层拦语法错误第二层拦决策错误第三层拦环境冲突。对绝大多数项目第一层必须先做第三层上线前必须做。5.4 评测结果怎么用加护栏还是换模型拿到评测报告后最常见的误操作是立刻换模型。我的经验是90%的失败来自工具参数格式错、状态不同步、缺少重试机制这些应该用护栏解决。只有当三种“工程类错误”全部排除后仍有20%以上任务因为理解偏差失败才值得换更大的模型或改提示词。评测的意义是区分“工程问题”和“模型问题”不是找借口换模型。汇报时也建议按“决策层错误/工具层错误/环境层错误”分类团队看完就知道先修哪一块。这套分类方法比任何可视化报表都好用。6. 让Agent真的下地干活三个验证技巧与投入回报判断6.1 复现综述结论的最小实验一张表判断方向值不值得做不用一比一复现综述里的实验最小可行实验是挑一个现有手工流程用Agent替换掉其中的“读、判、写”三段跑两周采样。验证项手工基线Agent实验值通过标准单任务平均耗时8分钟40秒降到原1/5以下任务完成率99%85%不低于85%且人工可在10秒内接管单次任务成本2元时间折算0.5元token接口低于手工基线兜底率无超时/超步人工接管兜底率低于20%这四条能定基线就先用历史数据定定不了就跑两周采样再说。任何一条不过先不要扩大投入。6.2 进阶路径牢牢握住“确定性”只放开“规划”从自动化脚本到Agent最稳的跨度是工具集和状态保持脚本一样的确定性只把“规划”这一步交给模型。状态更新和重试让Agent决定会导致行为不可控。更好的做法是给状态更新写死重试# 状态未更新时的重试策略最多重试2次每次间隔3秒 for attempt in range(2): result business_api.call(action.params) if result.state_version current_env.version: state.update(result) break if attempt 1: human_review_queue.push(action) # 两次未同步进人工兜底逻辑说明这套逻辑比让LLM反复“思考为什么没同步”成本低得多也符合综述里“行动必须产生环境变化”的定义。生产环境下地干活靠的不是模型聪明而是工程确定性和人工兜底的完整闭环。这个方向值得投入的标准我总结成一句话如果一个月至少有100次以上的重复“读-判-写”劳动就值得把Agent建起来如果低于这个频次脚本加上简单规则更划算。方向上学习路线建议就从综述的定义出发按“最小Agent→三层评测→背压与状态锁→人工兜底”这个顺序走不急着追新框架。我现在的习惯是每次碰到Agent行为不可解释的故障就先回头读一遍“记忆-规划-工具-行动”的定义然后问三个问题它有没有改变环境环境反馈有没有进记忆下一步规划有没有用上这个反馈大多数看似在动的Agent实际只答对了第一个问题。这个习惯帮我避开了很多次看起来有效但其实不可控的翻车希望帮到你。本文还有配套的精品资源点击获取