AI Agent 入门:从"会回答"到"可靠地完成任务"
Agent 并不等于一个接上工具的大模型。真正的 Agent,是一个能持续观察、行动、验证并纠错的闭环系统。**
文章目录
- [AI Agent 入门:从"会回答"到"可靠地完成任务"](#AI Agent 入门:从“会回答”到“可靠地完成任务”)
-
- 一、先记住一个最小公式
- 二、为什么"能聊天"不等于"能完成任务"
- [三、ReAct:让 Agent 真正运行起来的循环](#三、ReAct:让 Agent 真正运行起来的循环)
- [四、"模型即 Agent"也不意味着不需要工程系统](#四、“模型即 Agent”也不意味着不需要工程系统)
- [五、Harness:从 Demo 到可靠系统的分界线](#五、Harness:从 Demo 到可靠系统的分界线)
- [六、从 Prompt 工程走向 Loop 工程](#六、从 Prompt 工程走向 Loop 工程)
- [七、工作流与自主 Agent 应该怎么选](#七、工作流与自主 Agent 应该怎么选)
- 八、安全不是一个提示词,而是三层边界
- 九、第一章中可以反复复用的五个模式
-
- [1. Proposer--Reviewer](#1. Proposer–Reviewer)
- [2. Progressive Disclosure](#2. Progressive Disclosure)
- [3. Append-only](#3. Append-only)
- [4. Boundary Set + Retention Set](#4. Boundary Set + Retention Set)
- [5. Minimal Diff + Rollback](#5. Minimal Diff + Rollback)
- [十、以后我会用这五个问题判断一个 Agent](#十、以后我会用这五个问题判断一个 Agent)
- 十一、我的实践计划:先亲手破坏一次上下文
- 总结
一、先记住一个最小公式
理解 AI Agent,可以从下面这个公式开始:
text
Agent = LLM + 上下文 + 工具
如果用人的身体来类比:
| 组成 | 类比 | 在 Agent 中负责什么 |
|---|---|---|
| LLM | 大脑 | 理解目标、推理、规划下一步行动 |
| 上下文 | 眼睛与短期记忆 | 告诉模型当前发生了什么、此前做过什么 |
| 工具 | 手脚 | 搜索、读文件、写代码、调用 API、操作外部系统 |
这个公式看起来很简单,但它帮我划清了两个容易混淆的概念:
- 模型负责做决策,不等于模型亲自执行了动作。
- Agent 在环境中行动,但环境本身不属于 Agent。
一个更完整的关系如下:
#mermaid-svg-GZUqHJbfzflTEPHi{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GZUqHJbfzflTEPHi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GZUqHJbfzflTEPHi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GZUqHJbfzflTEPHi .error-icon{fill:#552222;}#mermaid-svg-GZUqHJbfzflTEPHi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GZUqHJbfzflTEPHi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GZUqHJbfzflTEPHi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GZUqHJbfzflTEPHi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GZUqHJbfzflTEPHi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GZUqHJbfzflTEPHi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GZUqHJbfzflTEPHi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GZUqHJbfzflTEPHi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GZUqHJbfzflTEPHi .marker.cross{stroke:#333333;}#mermaid-svg-GZUqHJbfzflTEPHi svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GZUqHJbfzflTEPHi p{margin:0;}#mermaid-svg-GZUqHJbfzflTEPHi .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-GZUqHJbfzflTEPHi .cluster-label text{fill:#333;}#mermaid-svg-GZUqHJbfzflTEPHi .cluster-label span{color:#333;}#mermaid-svg-GZUqHJbfzflTEPHi .cluster-label span p{background-color:transparent;}#mermaid-svg-GZUqHJbfzflTEPHi .label text,#mermaid-svg-GZUqHJbfzflTEPHi span{fill:#333;color:#333;}#mermaid-svg-GZUqHJbfzflTEPHi .node rect,#mermaid-svg-GZUqHJbfzflTEPHi .node circle,#mermaid-svg-GZUqHJbfzflTEPHi .node ellipse,#mermaid-svg-GZUqHJbfzflTEPHi .node polygon,#mermaid-svg-GZUqHJbfzflTEPHi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GZUqHJbfzflTEPHi .rough-node .label text,#mermaid-svg-GZUqHJbfzflTEPHi .node .label text,#mermaid-svg-GZUqHJbfzflTEPHi .image-shape .label,#mermaid-svg-GZUqHJbfzflTEPHi .icon-shape .label{text-anchor:middle;}#mermaid-svg-GZUqHJbfzflTEPHi .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GZUqHJbfzflTEPHi .rough-node .label,#mermaid-svg-GZUqHJbfzflTEPHi .node .label,#mermaid-svg-GZUqHJbfzflTEPHi .image-shape .label,#mermaid-svg-GZUqHJbfzflTEPHi .icon-shape .label{text-align:center;}#mermaid-svg-GZUqHJbfzflTEPHi .node.clickable{cursor:pointer;}#mermaid-svg-GZUqHJbfzflTEPHi .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GZUqHJbfzflTEPHi .arrowheadPath{fill:#333333;}#mermaid-svg-GZUqHJbfzflTEPHi .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GZUqHJbfzflTEPHi .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GZUqHJbfzflTEPHi .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GZUqHJbfzflTEPHi .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GZUqHJbfzflTEPHi .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GZUqHJbfzflTEPHi .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GZUqHJbfzflTEPHi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GZUqHJbfzflTEPHi .cluster text{fill:#333;}#mermaid-svg-GZUqHJbfzflTEPHi .cluster span{color:#333;}#mermaid-svg-GZUqHJbfzflTEPHi div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GZUqHJbfzflTEPHi .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GZUqHJbfzflTEPHi rect.text{fill:none;stroke-width:0;}#mermaid-svg-GZUqHJbfzflTEPHi .icon-shape,#mermaid-svg-GZUqHJbfzflTEPHi .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GZUqHJbfzflTEPHi .icon-shape p,#mermaid-svg-GZUqHJbfzflTEPHi .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GZUqHJbfzflTEPHi .icon-shape .label rect,#mermaid-svg-GZUqHJbfzflTEPHi .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GZUqHJbfzflTEPHi .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GZUqHJbfzflTEPHi .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GZUqHJbfzflTEPHi :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Agent
组织、约束、验证、纠错
观察结果 Observation
动作 Action
外部环境
上下文
LLM
工具调用
Harness
因此,Agent 不是一个静态程序,而是一个不断与外部世界交换信息的系统。
二、为什么"能聊天"不等于"能完成任务"
普通聊天模型接收一段文字,再生成一段文字。Agent 面对的则是一个开放过程:它需要根据当前状态决定下一步做什么,并根据行动结果继续调整。
这背后有两个重要概念:
- 观察空间:Agent 能看见哪些信息。
- 动作空间:Agent 被允许执行哪些操作。
比如,让模型"分析一个本地 PDF 里的数据并换算成人民币":
- 如果没有读取 PDF 的工具,它根本看不见数据。
- 如果没有汇率工具,它只能依赖旧知识或猜测。
- 如果工具执行完却没有把结果返回给模型,它就不知道动作是否成功。
所以,很多看起来像"模型不够聪明"的问题,实际上是接口问题:该看的信息没进入上下文,该做的动作不在工具集合里。
这也给了我一个很实用的排查顺序:Agent 表现不好时,不要先急着换更大的模型,而要先问:
- 它是否看到了完成任务所需的信息?
- 它是否拥有完成任务所需的动作?
- 动作的真实结果是否重新回到了上下文?
三、ReAct:让 Agent 真正运行起来的循环
Agent 最经典的运行方式是 ReAct:Reasoning and Acting,也就是一边推理,一边行动。
#mermaid-svg-o9CUjl9sExLgDgld{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-o9CUjl9sExLgDgld .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-o9CUjl9sExLgDgld .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-o9CUjl9sExLgDgld .error-icon{fill:#552222;}#mermaid-svg-o9CUjl9sExLgDgld .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-o9CUjl9sExLgDgld .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-o9CUjl9sExLgDgld .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-o9CUjl9sExLgDgld .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-o9CUjl9sExLgDgld .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-o9CUjl9sExLgDgld .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-o9CUjl9sExLgDgld .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-o9CUjl9sExLgDgld .marker{fill:#333333;stroke:#333333;}#mermaid-svg-o9CUjl9sExLgDgld .marker.cross{stroke:#333333;}#mermaid-svg-o9CUjl9sExLgDgld svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-o9CUjl9sExLgDgld p{margin:0;}#mermaid-svg-o9CUjl9sExLgDgld .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-o9CUjl9sExLgDgld .cluster-label text{fill:#333;}#mermaid-svg-o9CUjl9sExLgDgld .cluster-label span{color:#333;}#mermaid-svg-o9CUjl9sExLgDgld .cluster-label span p{background-color:transparent;}#mermaid-svg-o9CUjl9sExLgDgld .label text,#mermaid-svg-o9CUjl9sExLgDgld span{fill:#333;color:#333;}#mermaid-svg-o9CUjl9sExLgDgld .node rect,#mermaid-svg-o9CUjl9sExLgDgld .node circle,#mermaid-svg-o9CUjl9sExLgDgld .node ellipse,#mermaid-svg-o9CUjl9sExLgDgld .node polygon,#mermaid-svg-o9CUjl9sExLgDgld .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-o9CUjl9sExLgDgld .rough-node .label text,#mermaid-svg-o9CUjl9sExLgDgld .node .label text,#mermaid-svg-o9CUjl9sExLgDgld .image-shape .label,#mermaid-svg-o9CUjl9sExLgDgld .icon-shape .label{text-anchor:middle;}#mermaid-svg-o9CUjl9sExLgDgld .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-o9CUjl9sExLgDgld .rough-node .label,#mermaid-svg-o9CUjl9sExLgDgld .node .label,#mermaid-svg-o9CUjl9sExLgDgld .image-shape .label,#mermaid-svg-o9CUjl9sExLgDgld .icon-shape .label{text-align:center;}#mermaid-svg-o9CUjl9sExLgDgld .node.clickable{cursor:pointer;}#mermaid-svg-o9CUjl9sExLgDgld .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-o9CUjl9sExLgDgld .arrowheadPath{fill:#333333;}#mermaid-svg-o9CUjl9sExLgDgld .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-o9CUjl9sExLgDgld .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-o9CUjl9sExLgDgld .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-o9CUjl9sExLgDgld .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-o9CUjl9sExLgDgld .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-o9CUjl9sExLgDgld .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-o9CUjl9sExLgDgld .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-o9CUjl9sExLgDgld .cluster text{fill:#333;}#mermaid-svg-o9CUjl9sExLgDgld .cluster span{color:#333;}#mermaid-svg-o9CUjl9sExLgDgld div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-o9CUjl9sExLgDgld .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-o9CUjl9sExLgDgld rect.text{fill:none;stroke-width:0;}#mermaid-svg-o9CUjl9sExLgDgld .icon-shape,#mermaid-svg-o9CUjl9sExLgDgld .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-o9CUjl9sExLgDgld .icon-shape p,#mermaid-svg-o9CUjl9sExLgDgld .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-o9CUjl9sExLgDgld .icon-shape .label rect,#mermaid-svg-o9CUjl9sExLgDgld .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-o9CUjl9sExLgDgld .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-o9CUjl9sExLgDgld .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-o9CUjl9sExLgDgld :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
是
思考 / 推理
选择并调用工具
观察工具结果
任务完成了吗?
输出结果
它的核心代码甚至可以压缩成下面几行:
python
trajectory = [user_request]
while True:
context = stable_prefix + trajectory
decision = model(context)
trajectory.append(decision)
if not decision.tool_calls:
return decision.answer
for call in decision.tool_calls:
checked_call = harness.validate(call)
observation = environment.execute(checked_call)
trajectory.append(observation)
这里最值得注意的不是 while 循环,而是不断增长的 trajectory,也就是 Agent 的行动轨迹。它通常包含:
- 用户最初的目标;
- 模型已经做出的判断;
- 发起过的工具调用;
- 工具返回的真实结果;
- 失败、重试和中间状态。
每一轮决策,都建立在前面所有轮次留下的信息上。
上下文不是"多塞一点资料"
第一章用消融实验说明了不同上下文成分的作用:
| 被拿掉的内容 | Agent 会发生什么 |
|---|---|
| 工具定义 | 不知道自己能做什么,可能转而编造结果 |
| 工具返回值 | 看不见动作结果,容易盲目重试 |
| 历史轨迹 | 忘记已经做过什么,产生重复操作 |
| 显式推理 | 部分任务仍能靠结果继续,但复杂规划更容易退化 |
这让我意识到:上下文管理的目标不是让 Prompt 越长越好,而是让模型在当前一步拿到恰好足够、可信且结构清晰的信息。
更重要的是,Agent 输出了一段看起来合理的话,并不代表任务已经完成。完成状态应该由环境中的事实决定,例如文件是否真的生成、数据库是否真的更新、测试是否真的通过。
四、"模型即 Agent"也不意味着不需要工程系统
现在的大模型经过工具调用和强化学习训练后,能够自己判断什么时候搜索、什么时候写代码、什么时候继续推理。这种趋势可以称为"模型即 Agent"。
但这里很容易产生一个误解:既然模型越来越强,是不是外面的 Agent 框架就没有用了?
答案是否定的。
模型可以学会的是一种行动策略:在什么状态下选择什么工具、传入什么参数。真正的工具实现、权限控制、执行过程和结果校验,仍然发生在模型之外。
因此,更准确的公式是:
text
Agent = Model + Harness
其中:
text
Harness = 上下文管理 + 工具接口 + 约束 + 验证 + 纠正
模型越强,能够自主完成的步骤越多;但步骤越多,潜在错误和风险也会累积。于是 Harness 不会消失,而是会从"教模型怎么做"逐渐转向"给模型提供边界、证据和恢复能力"。
五、Harness:从 Demo 到可靠系统的分界线
我把 Harness 理解为包裹在模型外面的运行系统。它不负责替模型思考,却决定模型能看到什么、能做什么,以及出错以后怎么办。
| 要素 | 作用 | 缺失后的典型问题 |
|---|---|---|
| 上下文 Context | 构造当前决策所需的信息 | 模型遗漏事实、重复劳动 |
| 工具 Tools | 把决策转换为外部动作 | 只能给建议,不能完成任务 |
| 约束 Constrain | 限制动作、参数、权限和范围 | 越权操作或扩大影响面 |
| 验证 Verify | 根据外部事实判断是否成功 | 把"模型说成功了"误当成成功 |
| 纠正 Correct | 重试、回滚、续跑或转人工 | 一次失败后整条任务中断 |
这五个要素又可以分成两组:
- 上下文和工具让 Agent 变得有能力。
- 约束、验证和纠正让 Agent 变得可靠。
例如,代码 Agent 修改完程序后,不能只问模型"你修好了吗",而应该运行测试、静态检查或真实场景验证。验证依赖的是环境事实,而不是模型对自己的评价。
当验证失败时,系统还要决定下一步:补充信息后重试、恢复到安全状态、从断点继续,还是超过阈值后交给人处理。这才是完整的任务闭环。
六、从 Prompt 工程走向 Loop 工程
第一章给出了一条很有启发的工程演进路线:
text
Prompt Engineering
⊂ Context Engineering
⊂ Harness Engineering
⊂ Loop Engineering
⊂ Graph Engineering
我的理解是:
- Prompt 工程关注这一轮应该怎样问模型。
- 上下文工程关注这一轮究竟应该让模型看到什么。
- Harness 工程关注模型如何安全地连接外部能力。
- Loop 工程关注任务如何在多轮观察与行动中收敛。
- Graph 工程关注多个步骤、角色和分支如何协作。
Prompt 仍然重要,但如果系统需要长时间运行,仅靠"写一个神奇提示词"远远不够。真正的难点已经转向状态、接口、反馈、验证和恢复。
七、工作流与自主 Agent 应该怎么选
并不是所有任务都应该交给一个完全自主的 Agent。
| 方案 | 适合什么任务 | 优点 | 代价 |
|---|---|---|---|
| 单次 Prompt | 简单、边界清楚的一次性任务 | 成本低、实现快 | 不能处理长链路反馈 |
| 工作流 Workflow | 流程稳定、步骤可预先确定 | 可预测、容易测试 | 面对变化时不够灵活 |
| 自主 Agent | 路径未知、需要探索和动态决策 | 灵活、适应性强 | 成本和不确定性更高 |
| 混合模式 | 大部分生产任务 | 关键路径稳定,局部允许自主 | 设计复杂度更高 |
比较稳妥的升级顺序是:
text
先优化单次 Prompt → 再固化为工作流 → 确有需要时才增加自主性
我很认同这种克制。自主性不是越高越先进,而应该与任务的不确定性匹配。稳定环节交给确定性代码,只有真正需要判断和探索的局部才交给模型。
八、安全不是一个提示词,而是三层边界
"请不要执行危险操作"只能算提醒,不能算可靠的安全设计。真正的护栏至少要覆盖三层:
- 上下文层:模型能够看见哪些数据,敏感信息是否被过滤。
- 执行层:模型可以调用哪些工具,允许使用哪些参数和权限。
- 数据层:即使前面出错,外部世界最终允许被改成什么状态。
例如,一个数据库 Agent 即使生成了删除语句,执行层仍可禁止高风险 SQL,数据层还可以通过事务、权限和备份降低损失。
对于付款、发布、删除、授权等高风险动作,应引入人工确认;对于普通失败,可以设置重试次数、超时和熔断。与此同时,护栏也要测试"误拒绝":过度保守、什么都不敢做的 Agent 同样无法完成任务。
九、第一章中可以反复复用的五个模式
除了 Agent 的基本结构,我还记下了五个贯穿后续章节的设计模式:
1. Proposer--Reviewer
一个组件提出方案,另一个组件检查方案。生成和验证分离,比让同一个模型自我保证更可靠。
2. Progressive Disclosure
先给最必要的信息,需要时再逐步展开。它能减轻上下文噪声,也能减少不必要的工具和权限暴露。
3. Append-only
关键轨迹尽量追加记录,不直接覆盖历史。这样失败可追溯、过程可审计、任务可续跑。
4. Boundary Set + Retention Set
一套规则决定什么允许进入系统,另一套规则决定什么值得长期保留。前者控制风险,后者控制上下文成本。
5. Minimal Diff + Rollback
每次只做完成目标所需的最小改动,并保留恢复路径。Agent 出错不可避免,关键是让错误影响面足够小。
十、以后我会用这五个问题判断一个 Agent
读完第一章后,我给自己留下了一张最小检查表。以后无论是读项目还是自己设计 Agent,我都会先问:
- 它看见什么? 信息从哪里来,是否完整、可信、及时?
- 它能做什么? 工具有哪些,动作和参数边界是什么?
- 谁来证明它做对了? 是否有独立于模型自述的验证证据?
- 失败后怎么恢复? 能否重试、回滚、续跑或转人工?
- 最坏会影响什么? 权限、数据和外部副作用是否被限制?
这五个问题比"用了什么模型""Prompt 写了多长"更接近一个 Agent 系统的真实质量。
十一、我的实践计划:先亲手破坏一次上下文
第一章配套项目中,最适合入门的是 chapter1/context 消融实验。它可以分别移除历史、推理、工具调用和工具结果,让我们直接观察 Agent 会怎样退化。
bash
# 在项目根目录安装第一章依赖
uv sync --locked --extra ch1
source .venv/bin/activate
cd chapter1/context
cp env.example .env
# 在 .env 中配置一个可用的模型 API Key
# 先体验完整 Agent
python main.py --mode interactive --provider dashscope
# 再运行上下文消融对照
python main.py --mode ablation --provider dashscope
第一次实践时不必逐行阅读所有 Provider 适配代码,可以沿着下面的路径学习:
text
main.py
→ agent.py
→ 上下文如何组装
→ 工具如何调用
→ 结果如何写回 trajectory
→ 不同消融模式如何改变行为
学习目标也不是记住框架 API,而是亲眼验证一件事:Agent 的能力来自闭环;闭环中任何一个关键反馈被拿掉,系统行为都会发生变化。
总结
第一章表面上在介绍 LLM、上下文、工具和 ReAct,实际上建立了一套判断 Agent 系统的基本坐标:
text
能力:模型 + 上下文 + 工具
可靠性:约束 + 验证 + 纠正
运行方式:观察 → 决策 → 行动 → 再观察
工程目标:不是生成一个答案,而是让任务在真实环境中可靠完成
如果只记住一句话,我会记住:
不要只构建一个会说"我完成了"的模型,要构建一个能够用外部事实证明任务已经完成的系统。