第 2 章 四阶认知:从 Prompt 到 Loop
传统程序员切入 Agent 工程,认知会经历四个阶段。这不是什么理论框架,是我自己走过的路,也是我观察到的绝大多数人卡住的地方。
开篇:所有人都从调 prompt 开始
如果你观察一群刚接触 Agent 的程序员,会发现一个高度一致的模式——大家的第一反应都是研究 prompt。
这很正常。Prompt 是最显眼的旋钮,转一下就有反馈,调一句就有变化。新手最自然的动作就是往 prompt 里加规则、加约束、加示例,然后跑一遍看效果。我自己也是这么开始的,第 1 章讲的那三天调 prompt 的经历就是明证。
但问题在于,很多人会卡在这一步。
我见过不少工程师,做了好几个月 Agent,聊天的话题还停留在"你用的什么 prompt""能不能分享下你的 system prompt"。他们的认知模型是这样的:Agent 好不好 = prompt 写得好不好 + 模型选得准不准。
这个模型没错,但它只覆盖了整件事的一小块。Prompt 是起点,不是终点。 从 prompt 往外走,还有三个层级在等着你,而且越往外,越是 Agent 工程的真正核心。
这一章,我想把这条路径画清楚。不是为了让你们按部就班地"升级",而是为了让你知道——如果你现在卡住了,卡在哪一阶,下一阶是什么。
四阶是什么
我先给个全景,然后逐阶展开。
| 阶段 | 关注点 | 典型问题 | 成熟标志 |
|---|---|---|---|
| 阶 1 Prompt | 怎么跟模型说话 | "怎么写 prompt 让模型听话" | 会写示例、能控制输出格式 |
| 阶 2 Context | 给模型什么信息 | "模型需要哪些上下文才能决策" | 会分层注入信息、管理上下文窗口 |
| 阶 3 Harness | 模型怎么跟系统交互 | "工具怎么设计、错误怎么返回" | 工具描述当 prompt 写、错误信息可操作 |
| 阶 4 Loop | 执行循环怎么设计 | "用状态机还是自决循环、触发和响应怎么分" | 知道"保持循环简单,复杂度下沉" |
你可以把它理解成关注点"从模型逐渐外移到系统"的过程。阶 1 你盯着模型本身(怎么跟它说话),阶 4 你已经在设计整个系统的骨架(循环怎么转)。中间两阶是过渡。
有一点要提前说清楚:这四阶不是"低级到高级"的鄙视链。 你不会因为进了阶 4 就不用管 prompt 了——阶 1 的能力是后面所有阶的基础。四阶的意思是,你的关注范围在扩大,从只盯着 prompt,扩大到同时关注 context、harness、loop。
阶 1 Prompt:大多数人出发,也大多数人在此止步
第一阶不需要多讲——调 prompt。怎么写指令模型才听,怎么给示例模型才准,怎么控制输出格式。
这一阶有一个明确的成熟标志:你不再依赖"说漂亮话"来让模型听话,而是学会了用结构化的方式跟它沟通。 具体来说就是会写示例(术语叫 few-shot,第 1 章解释过),会明确指定输出格式("请输出 JSON,字段包含……"),会在 prompt 里区分"必须遵守的规则"和"参考信息"。
为什么大多数人卡在这一阶?因为 prompt 的反馈太即时了。你改一句,跑一遍,马上看到效果,这种即时的掌控感会让人上瘾,也会让人产生一种错觉——"只要 prompt 调得够好,Agent 就没问题"。这个错觉会把你锁死在阶 1。
阶 1 有一个不那么显眼但很重要的成熟标志:你开始把 system prompt 分区写,而不是平铺。下面是我项目里 system prompt 的真实结构:
# 行为准则(硬性约束)
- 默认不主动回复,只在被直接提及时才响应
- 以下情况可以主动回复:有人问问题、有人约活动、有人提到费用...
- 以下情况不要回复:纯问候、确认消息、与社区无关的闲聊...
# 什么该保存为记忆(规则 + 反例)
- 保存:确定的计划、费用记录、关于成员的事实
- 不保存:闲聊、问候、天气、"明天几点出发"这类待定信息
# 输出风格
- 结论先行,不要描述你的操作过程
- 操作确认要简洁:做了什么 + 一句话确认注意这个结构——它把"必须遵守的规则"(行为准则)和"参考信息"(输出风格)分开了,而且每条规则后面都跟了反例("不保存:闲聊、问候")。这些反例不是一开始就有的,是踩了坑之后一条条加上去的。好的 prompt 不是写出来的,是从错误里长出来的。
打破阶 1 的错觉,第 1 章已经讲过方法了:当你发现 prompt 怎么调都调不好的时候,往 prompt 之外看。
阶 2 Context:给模型正确的信息,比给模型正确的指令更重要
往 prompt 之外看的第一站,是 Context。
Context 是什么?就是模型每次做决策时,能看到的所有信息。它包括你写的 system prompt,也包括用户消息、历史对话、工具返回的结果、从数据库里检索出来的资料。所有这些加在一起,构成模型那个瞬间的"视野"。
我意识到 Context 的重要性,是因为一个很具体的困扰:我的 Agent 偶尔会"健忘"。明明上一步刚查过某个信息,下一步它就忘了,重新查一遍。明明历史对话里说过一个关键约束,它到了后面就开始忽略。
一开始我以为又是 prompt 的问题,于是在 system prompt 里加规则:"注意参考历史对话""不要重复查询"。没用。因为这些规则是"提示"模型要记住,但模型实际能看到的历史信息,可能早就被截断或者淹没在无关内容里了。
问题不在"提示它记住",在"它到底能看到什么"。
这就是 Context 层面的事。阶 2 的核心认知是:模型的决策质量,取决于它在决策那个瞬间能看到什么信息。 这跟你给它的指令写得好不好是两回事——指令是"告诉它怎么做",context 是"让它看到什么"。一个瞎子,你指令写得再清楚,他也走不了路。
阶 2 的成熟标志是:你开始主动管理模型的视野。哪些信息该放进上下文、哪些该丢掉、以什么顺序放、历史对话留多少截多少、检索回来的资料怎么压缩——这些才是你花时间琢磨的事。Prompt 从"唯一重要的东西"变成了"context 的一部分"。
讲个真实的例子。我的 Agent 有一项功能是调用外部工具执行耗时任务(要一两分钟),任务完成后回调通知 Agent。但回调的时候,模型已经"失忆"了——它不记得自己当初为什么要启动这个任务,因为那段对话早就被新的消息挤出了上下文窗口。
光靠 prompt 解决不了这个问题——你写"请记住之前的任务"也没用,因为它真的看不见了。我的解法是在回调时往上下文里注入一段恢复提示,主动告诉模型"你正在处理一个刚完成的任务,请先读取任务计划文件恢复上下文"。同时把任务计划写进一个文件,让模型自己去读。
具体到代码层面,我的上下文是分层组装的——不是把所有信息一股脑塞进去,而是分成五层,每层一个独立的消息:
func (b *PromptBuilder) Build(ctx BuildContext) []Message {
msgs := []Message{
SystemMsg(b.systemPrompt), // ① 静态系统提示
}
if len(ctx.Projects) > 0 {
msgs = append(msgs, SystemMsg(b.buildProjectContext())) // ② 活跃任务
}
if len(ctx.Memories) > 0 {
msgs = append(msgs, SystemMsg(b.buildMemoryContext())) // ③ 检索到的记忆
}
msgs = append(msgs,
SystemMsg(b.buildDynamicContext()), // ④ 社区动态 + 近期消息
b.buildUserMessage(), // ⑤ 当前用户消息
)
return msgs
}你看,系统提示、任务信息、记忆、动态上下文、用户消息——每一层都是独立注入的,有就放,没有就不放。这不是 prompt 调出来的,是 context 层面的工程设计。阶 2 到了这一步,你已经在做"信息架构"了,而不只是"写指令"了。
阶 3 Harness:模型和系统怎么交互
第 3 阶是这份手记花最多笔墨的地方——第 4 章讲工具设计,本质上就是在讲 harness。
Harness 是"模型之外的一切"。阶 1 你管模型(prompt),阶 2 你管信息(context),阶 3 你管模型和系统之间的交互接口(harness)——工具怎么定义、工具返回什么、工具失败了怎么办、工具之间的依赖关系怎么表达。
这个阶段的认知转变是最剧烈的,因为它彻底改变了你看待"接口"的方式。传统程序员把 API 文档当"给人看的说明",到了阶 3 你才明白,工具接口是给模型看的 prompt。工具描述里漏一句话,效果等同于 system prompt 里漏一句话。
阶 3 的成熟标志,第 4 章已经详细讲过了:工具描述当 prompt 写、错误信息要可操作、返回值要包含模型下一步需要的信息、工具间的依赖关系要显式表达。这里不重复。
我只想补一个观察:阶 3 是传统程序员优势最大的地方。 因为 harness 的本质是系统设计——接口设计、错误处理、数据流转——这些全是传统软件工程的看家本领。很多程序员在阶 1 和阶 2 觉得 Agent 工程"很新、很玄",到了阶 3 会突然有种回到主场的熟悉感。你之前写的那些分层架构、错误处理中间件、API 设计规范,全都能用上。
具象一点。拿"错误处理"这件事来说——传统程序里,一个 API 出错了,你返回一个错误码或抛一个异常,调用方(人 or 上层代码)来处理。但在 Agent 时代,调用方变成了模型,事情就不一样了。我在项目里把工具错误分成了四层,每层交给不同的"责任方"处理:
工具执行出错
│
├── Transient(瞬时错误)
│ 网络、限流、超时
│ → 机制层自动重试(模型根本不知道出过错)
│
├── LLM-recoverable(模型可自修正)
│ 参数格式错、缺少必填字段、路径不存在
│ → 错误信息回灌给模型,它自己改了重试
│
├── User-fixable(需要用户介入)
│ 权限不足、API Key 未配置、数据未同步
│ → 中断执行,告诉用户该做什么
│
└── Unexpected(未预期异常)
代码 bug、数据库连不上
→ 上抛异常,记日志,开发者来查这个四层分流,就是 harness 的核心工作之一。你看每一层的"责任方"都不一样——瞬时错误归机制层(重试),可自修正的错误归模型(改了重试),需要人介入的归用户,彻底崩了的归开发者。这不是 prompt 能做的事,也不是循环能做的事,纯粹是接口设计的功夫。
而每一层的处理质量,取决于你的 harness 设计得好不好。比如第二层"LLM-recoverable"——如果工具返回的错误信息是"参数错误"三个字,模型改不了;如果是"日期格式错误:你输入了'明天',请用 YYYY-MM-DD 格式",模型立刻就能改。这个差别,就是第 4 章讲的"错误信息要可操作"。
这就是阶 3 的本质——你不再只是跟模型说话,你在设计模型运转时面对的整个接口世界。 工具怎么定义、返回什么格式、出错时谁来解决,每一项都是你能掌控的工程设计。
阶 4 Loop:循环要简单,复杂度下沉
最后一阶,也是这份手记第 5 章的主题。
当你把 prompt、context、harness 都搞定了,最后一个问题是:这些东西怎么串起来?模型按什么流程去决策、调工具、拿到结果、再决策? 这就是 loop(执行循环)。
阶 4 的核心认知是第 5 章那句反复出现的话:保持循环简单,复杂度下沉到工具和提示词。
这句话听起来是个设计原则,但它背后藏着一个更深的认知转变:你要相信模型能自己做流程决策。
这个"相信"对传统程序员来说特别难。我们习惯了把流程写死——先做 A,再做 B,如果 C 就跳到 D。这是确定性思维的本能。但阶 4 要求你放下这种本能,把"下一步干什么"的决策权交给模型,自己只负责设计好工具(让它有能力决策)和护栏(让它不会跑飞)。
不是所有的流程都能交给模型——第 5 章讲过,确定性流程该用状态机就用状态机。但对于"需要模型判断"的那部分,你要学会放手,别在代码里替它做决定。
阶 4 的成熟标志是:你开始质疑"我的循环是不是太复杂了"。当你发现自己写的 Agent 越来越像一个庞大的状态机,而且每个状态都有复杂的跳转条件时,你会停下来想——这些跳转,是不是本来应该让模型自己判断的?
下面是我项目里真实的循环结构,用流程图画出来你会看得更清楚——"简单循环 + 显式护栏"长什么样:
消息进来
│
▼
┌──────────────────────────────────────────────────┐
│ Phase 1 · 构建上下文 │
│ (系统提示 + 记忆 + 动态上下文 + 用户消息) │
└──────────────────┬───────────────────────────────┘
▼
┌──────────────────────────────────────────────────┐
│ Phase 2 · ReAct 循环 (最多 N 轮) │
│ │
│ ┌─────────────┐ │
│ │ 模型决策 │◄──────────────────┐ │
│ └──────┬──────┘ │ │
│ │ │ │
│ 有工具调用? │ │
│ ├── 是 → 执行工具 → 结果回灌 ──────┘ │
│ └── 否 → 跳出循环 ↓ │
└──────────────────┬───────────────────────────────┘
▼
┌──────────────────────────────────────────────────┐
│ Phase 3 · 回复保证(护栏) │
│ │
│ 模型调了工具,但没产出文字? │
│ → 强制再调一次(不带工具),逼它总结输出 │
└──────────────────┬───────────────────────────────┘
▼
输出回复给用户你注意到了吗?Phase 2 这个循环里,没有任何 if-else 判断"该走哪条路"。模型自己在循环里决定:要不要调工具、调哪个、什么时候停。它说"我做完了"(不再请求工具调用),循环就自然结束。
我要做的事情只有两件:给它工具(Phase 2 循环里那些 tools),给它护栏(Phase 3 的回复保证)。我不编排它的流程,我只设计它手里的工具和它身后的护栏。 这就是阶 4 的样子——你从"编排流程的人"变成了"设计工具和护栏的人"。
一个重要的提醒:四阶不是线性的
画成一条直线是为了好讲,但真实的认知过程不是线性的。
我自己就是反复跳着走的。我在阶 1 调 prompt 调到怀疑人生(第 1 章),然后跳到阶 4 去重构循环(第 5 章),重构过程中发现工具设计有问题又跳回阶 3(第 4 章),改工具的时候发现上下文管理不对又跳到阶 2。真实的学习路径是螺旋的,不是阶梯的。
所以不用纠结"我现在在第几阶"或者"我什么时候能升到下一阶"。四阶的价值在于给你一张地图——当你卡住的时候,知道还有哪些方向可以看。你本来只盯着 prompt,现在你知道还有 context、harness、loop 三个方向可以排查。
这一章的工具:你在哪一阶?
下面这个自检不是考试,是帮你定位自己当前的"关注盲区"。大多数人会发现自己某一两阶特别强,另外一两阶几乎没关注过——那些没关注的,往往就是你 Agent 项目里隐藏问题的来源。
🔧 认知阶位自检
诚实回答以下问题,看看你的关注范围覆盖了哪几阶:
阶 1 Prompt
- [ ] 你会不会在 system prompt 里加示例来控制输出格式?
- [ ] 你能不能区分"必须遵守的规则"和"参考信息",并组织好它们的顺序?
阶 2 Context
- [ ] 你有没有主动管理过模型的"视野"?比如哪些历史对话保留、哪些丢弃?
- [ ] 当 Agent "健忘"的时候,你会不会去查"它那个瞬间到底能看到什么",而不是只知道改 prompt?
阶 3 Harness
- [ ] 你写工具描述的时候,是当成 API 文档写,还是当成 prompt 写?
- [ ] 工具失败时,返回的错误信息里有没有"下一步建议"?
阶 4 Loop
- [ ] 你的 Agent 执行循环,能用一句话描述吗?如果描述不出来,是不是太复杂了?
- [ ] 你有没有在代码里用 if-else 替模型做了它本该自己做的决定?
怎么读这个自检的结果
- 如果某一阶你几乎全勾不了,那这一阶大概率是你当前 Agent 项目的瓶颈所在
- 阶 1 和阶 2 是基础,阶 3 和阶 4 是进阶——但"进阶"不代表可以不管基础
- 最危险的情况是:只关注阶 1,对 2/3/4 完全没意识。这意味着你看不到 prompt 之外的问题
小结
四阶认知说到底就一句话:做 Agent 不等于调 prompt。
Prompt 是起点,但只是起点。从 prompt 往外走,有 context(给模型什么信息)、有 harness(模型怎么跟系统交互)、有 loop(循环怎么设计)。每一阶都是你能动手优化的地方,而且越往外越是 Agent 工程的真正核心。
传统程序员有一个隐藏优势:阶 3 和阶 4 涉及的系统设计,正是你们的主场。所以不用被"AI 工程"这个词吓到——它在很多方面,其实就是你熟悉的软件工程,换了一批新的约束条件而已。
从下一章开始,我们进入这份手记的第二部分——具体怎么把一个 Agent 做出来。第 3 章先讲一个最基础但最容易被忽视的东西:颗粒度。
下一章
第 3 章 · 颗粒度与验证 —— 为什么大多数 Agent 项目会失控,以及怎么不让它失控。