AI Agent 基础知识:从 LLM、上下文、工具到 ReAct 循环
过去的大模型应用,大多停留在“用户提问,模型回答”的对话模式。AI Agent 则更进一步:它不仅生成文字,还能围绕一个目标持续思考、调用工具、观察结果,并根据反馈调整下一步行动。
Cursor 修改代码后运行测试,Deep Research 多轮搜索并整理报告,Computer Use Agent 操作浏览器完成任务,本质上都在运行同一套闭环:
理解目标 → 制定行动 → 调用工具 → 观察结果 → 调整策略 → 直到任务完成
本文不展开某个具体框架,而是梳理构建现代 AI Agent 时最重要的基础概念。
一、什么是 AI Agent?
可以先用一个最小公式理解:
Agent = LLM + 上下文 + 工具
这三个部分分别对应大脑、眼睛和手脚:
| 组成部分 | 直观理解 | 核心作用 |
|---|---|---|
| LLM | 大脑 | 理解意图、分解任务、判断下一步做什么 |
| 上下文 | 眼睛 | 告诉模型当前任务、历史过程和环境反馈 |
| 工具 | 手脚 | 读取信息或改变外部世界 |
只有 LLM,没有工具,系统最多给出操作建议;只有工具,没有上下文,模型不知道任务进行到了哪一步;没有足够强的模型,系统又很难完成动态规划和异常处理。
因此,Agent 的能力不是某个组件单独决定的,而是三者协同的结果。
Agent 不等于环境
理解 Agent 时,还要区分它和 Environment(环境):
- Agent 内部包含模型、上下文管理和工具接口;
- 环境包含网页、文件、数据库、外部系统、用户和物理世界;
- Agent 通过接口观察环境,再通过工具对环境执行操作。
例如,文件读取工具属于 Agent 的工具接口,但磁盘里的真实文件属于环境。数据库查询适配器属于 Agent,而数据库中的状态仍属于环境。
这个边界很重要,因为生产系统需要明确:状态由谁维护、操作由谁执行、失败由谁处理,以及权限应该限制在哪里。
二、观察空间和动作空间
Agent 与外部世界的接口,可以拆成两个概念:
- 观察空间:Agent 能看到什么;
- 动作空间:Agent 能做什么。
没有进入上下文的信息,对模型来说就像不存在;没有被封装成工具的操作,即使模型知道方法,也只能停留在文字建议上。
因此,当底层模型不变时,提升 Agent 能力最直接的工程手段,往往不是不断修改提示词,而是:
- 为模型提供更完整、更准确的上下文;
- 为模型补充完成任务所必需的工具;
- 缩小无关信息和危险操作的暴露范围。
这也是通用 Agent 不断扩展能力边界的方式:浏览器让它看到网页,文件工具让它处理本地资料,终端让它运行程序,消息渠道让它与用户持续沟通。
但接口并不是越多越好。工具越多,上下文越复杂,误调用和安全风险也越高。真正有效的设计是:让 Agent 恰好看到完成任务所需的信息,并拥有边界清晰的行动能力。
三、工具:让模型真正采取行动
工具是 Agent 与外部世界交互的桥梁。根据用途,可以将工具大致分为五类:
1. 感知工具
负责获取信息,例如:
- 搜索网页;
- 读取文件;
- 查询数据库;
- 调用外部 API;
- 获取页面 DOM、截图或设备状态。
2. 执行工具
负责改变环境,例如:
- 写入或修改文件;
- 执行代码和命令;
- 调用业务接口;
- 发送消息;
- 操作浏览器或设备。
3. 协作工具
负责把部分任务交给其他参与者,例如:
- 委托子 Agent;
- 请求其他专业 Agent 分析;
- 在关键步骤请求用户确认;
- 将无法处理的问题转交人工。
4. 事件触发工具
负责启动 Agent,例如:
- 定时任务;
- 新邮件到达;
- Webhook 回调;
- 外部系统状态变化。
它们通常不是 Agent 主动调用的工具,而是环境向 Agent 输入观察、触发任务的通道。
5. 用户沟通工具
负责向用户传递结果或询问信息,例如:
- 文字消息;
- 邮件;
- 语音通话;
- 任务进度通知。
Tool Calling 是怎么运行的?
一次标准的工具调用通常包含四步:
- 开发者把工具名称、用途和参数格式提供给模型;
- 模型判断是否需要调用工具,并生成结构化参数;
- Agent 框架校验参数并执行工具;
- 工具结果被追加到上下文,模型根据结果决定下一步。
简化后的流程如下:
用户:查询上海今天的天气
↓
模型:调用 get_weather({ city: "上海" })
↓
工具:返回 { temperature: 31, weather: "晴" }
↓
模型:根据真实结果生成最终回答
模型负责“要不要调用、调用哪个、参数是什么”,真正的工具执行仍由模型外部的代码和基础设施完成。
工具设计的基本原则
- 名称和描述必须明确;
- 参数应尽量结构化,并提供边界说明;
- 工具结果应该稳定、可解析;
- 失败时返回可处理的错误,而不是模糊文本;
- 删除、支付、发信、部署等高风险操作,应使用专用工具;
- 高风险操作默认关闭,并增加预览、确认和审计;
- 代码执行等通用能力必须放入受限沙箱。
可以总结为一句话:
通用工具用于组合与探索,专用工具用于约束风险和落实业务规则。
四、上下文:决定 Agent 能看见什么
上下文不是单独一段提示词,而是模型在每次决策时能够获得的全部信息。通常包括五部分:
- 系统提示词:定义 Agent 的身份、目标、权限和行为准则;
- 工具定义:告诉模型有哪些工具,以及如何调用;
- 用户消息:用户提出的任务和补充信息;
- 模型历史回复:之前的判断、回答和工具调用;
- 工具执行结果:环境返回的真实反馈。
还可以将它们归纳成:
Agent 上下文 = 静态前缀 + 动态轨迹
静态前缀包括系统提示词和工具定义;动态轨迹则包括用户消息、模型回复和工具结果,并随着任务执行不断增长。
上下文缺失会直接破坏 Agent 的行为:
- 没有工具定义:模型不知道自己能做什么;
- 没有工具结果:模型看不到反馈,可能反复执行相同操作;
- 没有历史消息:模型会忘记已完成的步骤;
- 缺少关键环境信息:模型只能基于不完整事实做决策。
所以,上下文工程的核心不是“塞入越多信息越好”,而是在每个决策点提供足够、相关、可信的信息。
五、ReAct:Agent 的核心运行循环
ReAct 来自 Reasoning(思考)和 Acting(行动)。实际运行时还包含 Observation(观察):
思考 → 行动 → 观察 → 再思考
Agent 不会一次生成完整执行方案后盲目跑到底,而是在每次行动后读取环境反馈,再决定下一步。
一个最小循环可以写成下面的伪代码:
trajectory = [user_request]
while not finished:
context = stable_prefix + trajectory
decision = model(context)
trajectory.append(decision)
if decision.has_no_tool_call():
return decision.answer
for tool_call in decision.tool_calls:
validated_call = validate(tool_call)
observation = execute(validated_call)
trajectory.append(observation)其中:
stable_prefix是系统提示词和工具定义;trajectory是持续累积的任务轨迹;decision是模型当前做出的判断;observation是工具执行后返回的结果。
任务轨迹不仅用于继续推理,也是调试 Agent 的关键材料。通过轨迹可以检查:
- 模型为什么选择这个工具;
- 参数为什么出错;
- Agent 是否陷入重复循环;
- 哪一步开始偏离目标;
- 工具结果是否足以支撑最终结论。
因此,一个不能记录和回放轨迹的 Agent,很难真正进入生产环境。
六、从 Demo 到生产:Harness 工程
只把 LLM、上下文和工具接起来,可以做出一个能运行的 Demo,但不代表它可靠。
模型可能会:
- 编造不存在的工具;
- 传入错误参数;
- 重复执行相同动作;
- 在工具失败后继续生成错误结论;
- 未经确认执行高风险操作;
- 任务没有完成却提前宣布成功。
围绕模型运行的工程外壳通常称为 Harness。可以进一步写成:
Agent = Model + Harness
Harness = 上下文管理 + 工具接口 + 约束 + 验证 + 纠正
五项职责分别解决不同问题:
| 职责 | 解决的问题 |
|---|---|
| 上下文管理 | 模型当前应该看到哪些信息 |
| 工具接口 | 模型可以通过哪些方式观察或行动 |
| 约束 | 哪些操作允许执行,哪些必须禁止或确认 |
| 验证 | 如何判断执行结果是否正确 |
| 纠正 | 出错后如何重试、回退、换方案或转人工 |
例如,一个 Coding Agent 修改代码后,不能只相信模型说“已经修复”,而应该实际运行类型检查和测试。如果失败,就把错误输出反馈给模型继续修复;连续失败时触发熔断,停止无意义重试。
这说明 Agent 工程正在从“让模型能做事”,转向“让系统可靠地完成事情”。模型能力决定上限,Harness 则决定它能否安全、稳定地落地。
七、工作流与自主 Agent 的区别
不是所有任务都需要自主 Agent。根据执行路径是否预先确定,可以分成两种模式。
工作流:执行路径由代码规定
工作流适合步骤稳定、规则明确的任务。例如订票流程可以固定为:
- 核验身份;
- 查询航班;
- 用户确认;
- 完成支付;
- 生成订单。
优点是可预测、容易测试、安全边界清晰;缺点是遇到预设之外的情况时不够灵活。
自主 Agent:执行路径由模型动态决定
自主 Agent 不预先写死每一步,而是根据环境反馈决定下一步。它适合:
- 自动修改和验证代码;
- 多轮网络调研;
- 操作复杂网页;
- 步骤数量无法提前确定的开放任务。
自主性越高,成本、延迟和复合错误风险也越高,因此必须设置:
- 最大迭代次数;
- 明确的完成条件;
- 连续失败熔断;
- 工具调用权限;
- 高风险操作人工确认;
- 完整日志和可观测性。
应该怎么选择?
推荐按以下顺序判断:
- 一次 LLM 调用能解决,就不要引入循环;
- 固定步骤能解决,就使用工作流;
- 只有任务路径必须动态生成时,才使用自主 Agent;
- 生产系统通常采用混合模式:确定性流程负责关键边界,Agent 负责需要判断和探索的局部任务。
八、安全不是上线前再补的功能
Agent 可以调用工具并改变环境,风险远高于普通聊天机器人。安全能力应该从第一版架构就开始设计。
常见护栏可以分为三层:
输入侧
- 检测越狱和提示注入;
- 限制输入长度和格式;
- 过滤不相关或危险请求;
- 区分用户指令与网页、文件中的外部内容。
执行侧
- 对工具进行风险分级;
- 默认最小权限;
- 限制文件路径、网络访问和运行资源;
- 对支付、删除、发布等操作增加人工确认;
- 记录完整审计日志。
输出侧
- 检查个人信息和敏感数据泄露;
- 验证结构化结果;
- 对外发送前检查内容是否完整、可信;
- 不把未经验证的中间结论包装成最终结果。
护栏还要同时关注两种错误:危险请求被错误放行,以及合法请求被错误拒绝。安全不是拒绝得越多越好,而是在真实任务上保持风险和可用性的平衡。
九、构建 Agent 的三个实用原则
1. 保持简单
从最小可行方案开始。能用原生 API 完成,就不要一开始引入庞大框架;能用一个工具解决,就不要堆十个能力相近的工具。
2. 保持透明
保存任务状态、工具调用、执行结果和失败原因。对用户展示必要的进度和确认点,对开发者提供可回放的轨迹。
3. 从 Agent 视角设计工具
传统 API 主要服务确定性程序,Agent 工具接口则要降低模型理解和误用成本。名称应清晰,参数应减少歧义,危险组合应在接口层直接禁止,而不是依赖模型“自觉避免”。
十、一个适合初学者的实践顺序
理解概念之后,可以按以下顺序做一个最小 Agent:
- 调用一个支持 Tool Calling 的模型;
- 定义一个只读工具,例如天气查询或本地文档搜索;
- 实现“模型决策—执行工具—回传结果”的循环;
- 保存完整轨迹;
- 增加最大迭代次数和超时;
- 增加参数校验和错误反馈;
- 再加入一个写操作工具,并为它增加人工确认;
- 用成功、失败、重复调用和恶意输入四类用例测试。
完成这条链路后,再考虑长期记忆、RAG、多 Agent、Computer Use 和复杂工作流。否则很容易在基础闭环还不稳定时,就被框架和概念淹没。
总结
理解现代 AI Agent,可以先记住六句话:
- Agent 的最小组成是 LLM、上下文和工具。
- 上下文决定它能看到什么,工具决定它能做什么。
- ReAct 让模型在思考、行动和观察之间持续循环。
- 工作流强调确定性,自主 Agent 强调动态决策。
- Harness 通过约束、验证和纠正,让 Agent 从能运行走向可靠。
- 安全、权限、日志和人工接管不是附加功能,而是 Agent 架构的一部分。
真正有价值的 Agent,不是看起来更像人,也不是调用了最多的工具,而是能够在明确边界内持续推进任务,用真实反馈验证结果,并在失败时安全地停下来或恢复。
参考资料
本文是对《AI Agents in Depth》第一章“AI Agent 入门”的学习梳理与二次总结,重新组织了结构和表述,并补充了面向初学者的实践顺序,不是原文转载。