一条 Prompt 在 Agent 系统里怎么跑完
如果你真的想弄懂一个 Agent 系统,最好先别盯模型。先问一件更实际的事:
用户按下回车以后,这条 Prompt 到底经历了什么。
很多人第一次看 Agent 代码,会下意识把它想成一个大函数:读历史、调模型、执行工具、把答案吐回去。实际能跑进生产的系统通常不会这么写。它会把“怎么理解用户意图”“怎么维护运行状态”“怎么循环执行”拆开,不然上下文会很快乱掉。
可以把它看成三层。
第一层是会话层
会话层做的是产品语义,不是推理本身。
它会先看输入里有没有这些东西:
- Slash Command
- 文件引用
- Prompt 模板
- Skill
- 额外上下文
这些东西都不是模型天然会处理的,但它们决定了这条消息到底应该怎么进入系统。会话层要先把它们整理好,再交给运行层。
还有一个很重要的动作是上下文重建。会话跑久了,不可能把所有历史原样塞给模型。这里就会有压缩、摘要、活跃分支整理这些动作。它不是“删历史”,而是把现在还需要的东西重新拼出来。
第二层是运行层
运行层更像一个状态容器。
它接到的是一份已经整理好的任务,然后负责保存这轮运行里需要的东西,比如:
- messages
- tools
- model config
- steering 队列
- follow-up 队列
这层最重要的不是“会不会回答”,而是“这轮任务现在处在什么状态”。没有这个状态,Agent 只会像普通聊天接口,跑一会儿就散。
第三层是真正的循环
真正把任务跑完的,是 loop。
它的工作方式很简单:
- 把内部消息转成模型能吃的格式
- 调模型
- 如果模型要调工具,就执行工具
- 把工具结果再喂回去
- 继续下一轮,直到当前任务收束
这才是 Agent 和普通聊天接口最大的差别。聊天接口问完就完,Agent 要把执行链条接下去。
Steering 和 Follow-up 不是一回事
这里最容易混的是 steering 和 follow-up。
Steering 更像中途纠偏。当前任务还在跑,但方向不对了,系统可以把新的约束插进去,让下一轮尽快转向。
Follow-up 更像任务尾巴。当前这轮快结束了,但你又补了一句“顺手把这个也做了”,那它不该硬塞进当前回合,而是放到下一轮。
这种拆法很工程化。它不是在说“系统支持插话”,而是在说不同类型的插话应该走不同的路。
为什么这个边界重要
如果没有这三层,Agent 系统很容易变成一个混杂的大盒子:
- UI 的状态塞进推理层
- 历史消息塞进工具层
- 任务语义塞进模型 prompt
最后谁都能跑,谁都说不清。
这种拆法更清楚。会话层负责理解人,运行层负责记住任务,循环负责把事情做完。边界清楚以后,后面的持久化、恢复、工具钩子、观测,才有地方放。
一句话总结
如果把这条链路压成一句话,大概就是:
会话层先把用户意图整理成任务,运行层把任务装进状态里,循环层一轮一轮地把它做完。
这就是这里想讲清楚的 Agent 系统,不神秘,但很重要。