从强化学习的"经典定义"出发,理清 LLM Agent 的本质与边界。
建议先读《本章索引》;如果你是跳读,至少先看本章索引与本页 TL;DR。
课程理论地基,用来建立后续所有判断语言。
从强化学习的"经典定义"出发,理清 LLM Agent 的本质与边界。
先问控制流、动作空间、终止时机,再谈 agent 能力。
课程主线:稳定概念 + 经典论文 + 官方机制。
"Agent" 一词在 AI 领域比大模型早几十年。两本教科书定下了它的"标准像":
state s_t,按 策略 π(a | s) 输出 action a_t,环境返回新的 s_{t+1}。训练阶段还有 reward 用来优化 π;但训练完成后,rollout / inference 阶段 π 就被冻结,回路里只剩"观察 → 决策 → 动作"——这正是我们要类比的那一段。RL 推理阶段的 Agent–Environment 闭环(训练阶段会多一条 reward 回灌的箭头,这里略去——LLM Agent 对照的就是这张"已训练好的 π 在 rollout"的图)
这张图里有 5 个永恒不变的元素,构成 Agent 概念的"硬核"。LLM 带火了 Agent,但没有发明它,只是替换了其中一个零件——把 π 从"小神经网络 + 任务专属训练"换成了"大模型 + 通用预训练"。
π(a | s)。骨架完全保留,只换材料——这正是 "Agent" 这个词得以从 RL 平滑搬到 LLM 的原因。注意我们对照的是 RL 的 rollout / inference 阶段:π 在两边都是已经训练好、运行时冻结的。
| 元素 | RL Agent(推理阶段) | LLM Agent |
|---|---|---|
| Environment | Atari 游戏、机器人世界、交易市场…… | 文件系统 / 用户 / 浏览器 / API / shell / 数据库 |
| Observation | 像素帧、传感器读数、状态向量 | tool 返回值、user message(皆为文本) |
| Action | 离散/连续动作(按键、力矩) | tool call(带结构化参数)+ 自然语言回复 |
| Policy π | 已训练好的神经网络,rollout 时冻结;通常为任务专属(针对该环境训练) | LLM + system prompt,运行时同样冻结;属于通用 π,未必针对当前 agent 任务训练过 |
| Loop 终止 | 固定 step / episode 终止 | LLM 自宣 final answer,或外部熔断(max_steps、HITL 中断) |
对照到 RL 的推理阶段,五个零件可以一一对齐,没有"缺失项"——LLM Agent 不是某种残缺的 RL Agent,它就是 RL 推理回路在"通用 π + 文本动作空间"下的一种具体实例化。
真正的工程含义在另一头:既然 π 是冻结且通用的(不针对你的任务训练),运行时你能调的唯一变量就是 π 的输入——也就是上下文层:prompt engineering、tool design、context management、HITL。这就是为什么进阶 Agent 框架几乎所有篇幅都在讲"上下文怎么管"——能动的就这一处。
有了 RL 视角再回头给 LLM Agent 下定义,就不会被花哨术语带偏:
LLM Agent 是一个以 LLM 作为策略 π 的"感知 → 决策 → 行动"闭环;其动作空间由可调用 tool 集合定义,环境由这些 tool 的副作用域决定,终止由 LLM 自宣 final answer 或外部条件触发。
从这条定义出发,"是不是 Agent" 的判定就退化成三个问题——也就是下一节的三轴框架。
套用 RL 的语言:A 是"谁来调用 π",B 是"π 的输出值域",C 是"episode 何时结束"。Agent 的"agentic 程度",本质是这三件事中有多少件被下放给了 LLM。
| 轴 | 含义(RL 视角) | 失控时的失败模式 | 进阶框架常用什么稳住 |
|---|---|---|---|
| A 控制流归属 | 下一步动作是谁挑的?(代码 vs LLM 调 π) | 死循环 / 反复横跳 / 过早停止 | system prompt + planning tool + middleware |
| B 动作空间 | π 的值域有多开放?(枚举集 vs 自由组合) | hallucinated tool / 错误参数 / 无意义组合 | tool schema + 权限层 + subagent 切割 |
| C 终止时机 | episode 由谁宣告结束?(结构性终止 vs LLM 自宣) | 该停不停 / 不该停乱停 | final_answer 协议 + max_steps + HITL |
A 和 C 是循环问题——由 02 章讲的 "Agent Loop"(以及它的具体模式如 ReAct)解决;B 是接口问题——由 03 章讲的 Tool Calling 解决。这就是为什么 02 和 03 必须分开讲。
| # | 系统 | A | B | C | 是否 Agent |
|---|---|---|---|---|---|
| ① | for i in range(N): llm.call(...) |
代码 | 单一动作 | 计数器 | 否 · 脚本 |
| ② | 写死的 retrieve → rerank → generate DAG |
代码 | 每节点固定 | DAG 末端 | 否 · workflow |
| ③ | LangGraph + LLM router(在 3 条预定义边里选 1) | LLM (受限) |
枚举集 | DAG 末端 | 否 · agentic workflow |
| ④ | ReAct loop:自由 tool_call,由 LLM 决定何时输出 final_answer | LLM | 开放 | LLM 自宣 | 是 · Agent |
| ⑤ | 纯多轮 chatbot(无 tool) | LLM | 退化 仅"输出文本" |
用户挂断 | 否 · 对话系统 |
很多人会把 ③ 也叫 "Agent"——但它仍是 workflow,只是某个节点装了个 LLM 做路由。"LLM 选边 ≠ LLM 自治":边是被你预先列好的,agent 只是"在你画好的格子里跳"。这条线想清楚了,04 章 Agent vs Workflow 就基本不用学。
for 循环里调 100 次 LLM 仍是脚本,因为 A、C 都没下放。到 01-frameworks 这一章会反复回收这张表。每读到一个进阶框架特性,都问一遍:"它是在 A、B、C 上各做了什么?"
| 典型补强特性 | 主要影响轴 | 解决了"朴素 ReAct"什么洞 |
|---|---|---|
| Planning tool(write_todos) | A + 辅助 C | 长任务里 LLM 容易"走着走着忘了原目标"。把目标 / 待办外化为可被 LLM 自审的 markdown 状态,等于给 π 多了一层"自我提示"。 |
| Virtual File System | B + 救 05 章的 ctx 限制 | 把中间产物从 message 里搬出去,避免 token 爆炸 + lost-in-the-middle。新增 read_file / write_file / ls 等动作。 |
| Subagent | A + B + C | 把一段子控制流封装出去;主 loop 只看摘要,不被子任务的中间观察淹没。 |
| HITL / 权限层 | C + 卡 A | 让"人"成为高危动作前的硬卡点:既是安全层,也是在通用 π 不可信时,把"任务专属判断"以外部门控的方式注入回路。 |
01-frameworks/* 每读一节,都拿三轴问一遍:"这个框架在 A/B/C 上各做了什么?"04-comparative-architectures/* 拿三轴当对比表头,可以一页比清 Claude Code / Cursor / Codex / AutoGen 谁 agentic 到什么程度。常见误解:把 Agent 当成某个厂商的产品名词。更稳的做法是先回到 RL/AIMA 的闭环抽象,再看具体实现。
最小练习:用本页术语复述你熟悉的一个 agent 或 workflow,明确 A / B / C 三轴分别由谁控制。
下一页会把这页结论推进到《Agent Loop 与 ReAct》,帮助你把知识链条接起来。
章节定位:00 · Foundations。