One Request Lifecycle
This document is not available in the current locale. Showing fallback: zh
When This Page Helps
Traces one request from entry to write-back. Best read after Stage 2 when pieces need connecting.
Best Read Alongside
这是一份桥接文档。
它不替代主线章节,而是把整套系统串成一条真正连续的执行链。它要回答的问题是:
用户的一句话,进入系统以后,到底是怎样一路流动、分发、执行、再回到主循环里的?
为什么必须补这一篇
很多读者在按顺序看教程时,会逐章理解:
s01讲循环s02讲工具s03讲规划s07讲权限s09讲 memorys12-s19讲任务、多 agent、MCP
每章单看都能懂。
但一旦开始自己实现,就会很容易卡住:
- 这些模块到底谁先谁后?
- 一条请求进来时,先走 prompt,还是先走 memory?
- 工具执行前,权限和 hook 在哪一层?
- task、runtime task、teammate、worktree、MCP 到底是在一次请求里的哪个阶段介入?
所以你需要一张“纵向流程图”。
先给一条最重要的总图
用户请求
|
v
Query State 初始化
|
v
组装 system prompt / messages / reminders
|
v
调用模型
|
+-- 普通回答 -------------------------------> 结束本次请求
|
+-- tool_use
|
v
Tool Router
|
+-- 权限判断
+-- Hook 拦截/注入
+-- 本地工具 / MCP / agent / task / team
|
v
执行结果
|
+-- 可能写入 task / runtime task / memory / worktree 状态
|
v
tool_result 写回 messages
|
v
Query State 更新
|
v
下一轮继续
你可以把整条链先理解成三层:
Query LoopTool Control PlanePlatform State
第 1 段:用户请求进入查询控制平面
当用户说:
修复 tests/test_auth.py 的失败,并告诉我原因
系统最先做的,不是立刻跑工具,而是先为这次请求建立一份查询状态。
最小可以理解成:
query_state = {
"messages": [{"role": "user", "content": user_text}],
"turn_count": 1,
"transition": None,
"tool_use_context": {...},
}
这里的重点是:
这次请求不是“单次 API 调用”,而是一段可能包含很多轮的查询过程。
如果你对这一层还不够熟,先回看:
第 2 段:组装本轮真正送给模型的输入
主循环不会直接把原始 messages 裸发出去。
在更完整的系统里,它通常会先组装:
- system prompt blocks
- 规范化后的 messages
- memory section
- 当前轮 reminder
- 工具清单
也就是说,真正发给模型的通常是:
system prompt
+ normalized messages
+ tools
+ optional reminders / attachments
这里涉及的章节是:
s09memorys10system prompts10amessage & prompt pipeline
这一段的核心心智是:
system prompt 不是全部输入,它只是输入管道中的一段。
第 3 段:模型产出两类东西
模型这一轮的输出,最关键地分成两种:
第一种:普通回复
如果模型直接给出结论或说明,本次请求可能就结束了。
第二种:动作意图
也就是工具调用。
例如:
read_file("tests/test_auth.py")
bash("pytest tests/test_auth.py -q")
todo([...])
load_skill("code-review")
task_create(...)
mcp__postgres__query(...)
这时候系统真正收到的,不只是“文本”,而是:
模型想让真实世界发生某些动作。
第 4 段:工具路由层接管动作意图
一旦出现 tool_use,系统就进入工具控制平面。
这一层至少要回答:
- 这是什么工具?
- 它应该路由到哪类能力来源?
- 执行前要不要先过权限?
- hook 有没有要拦截或补充?
- 它执行时能访问哪些共享状态?
最小图可以这样看:
tool_use
|
v
Tool Router
|
+-- native tool handler
+-- MCP client
+-- agent/team/task handler
如果你对这一层不够清楚,回看:
第 5 段:权限系统决定“能不能执行”
不是所有动作意图都应该直接变成真实执行。
例如:
- 写文件
- 跑 bash
- 改工作目录
- 调外部服务
这时会先进入权限判断:
deny rules
-> mode
-> allow rules
-> ask user
权限系统处理的是:
这次动作是否允许发生。
相关章节:
第 6 段:Hook 可以在边上做扩展
通过权限检查以后,系统还可能在工具执行前后跑 hook。
你可以把 hook 理解成:
不改主循环主干,也能插入自定义行为的扩展点。
例如:
- 执行前记录日志
- 执行后做额外检查
- 根据结果注入额外提醒
相关章节:
第 7 段:真正执行动作,并影响不同层的状态
这是很多人最容易低估的一段。
工具执行结果,不只是“一段文本输出”。
它还可能修改系统别的状态层。
例子 1:规划状态
如果工具是 todo,它会更新的是当前会话计划。
相关章节:
例子 2:持久任务图
如果工具是 task_create / task_update,它会修改磁盘上的任务板。
相关章节:
例子 3:运行时任务
如果工具启动了后台 bash、后台 agent 或监控任务,它会创建 runtime task。
相关章节:
例子 4:多 agent / teammate
如果工具是 delegate、spawn_agent 一类,它会在平台层生成新的执行单元。
相关章节:
例子 5:worktree
如果系统要为某个任务提供隔离工作目录,这会影响文件系统级执行环境。
相关章节:
例子 6:MCP
如果调用的是外部 MCP 能力,那么执行主体可能根本不在本地 handler,而在外部能力端。
相关章节:
第 8 段:执行结果被包装回消息流
不管执行落在哪一层,最后都要回到同一个位置:
tool_result -> messages
这是整个系统最核心的闭环。
因为无论工具背后多复杂,模型下一轮真正能继续工作的依据,仍然是:
系统把执行结果重新写回了它可见的消息流。
这也是为什么 s01 永远是根。
第 9 段:主循环根据结果决定下一轮是否继续
当 tool_result 写回以后,查询状态也会一起更新:
messages变了turn_count增加了transition被记录成某种续行原因
这时系统就进入下一轮。
如果中间发生下面这些情况,控制平面还会继续介入:
- 上下文太长,需要压缩
- 输出被截断,需要续写
- 请求失败,需要恢复
相关章节:
第 10 段:哪些信息不会跟着一次请求一起结束
这也是非常容易混的地方。
一次请求结束后,并不是所有状态都随之消失。
会跟着当前请求结束的
- 当前轮 messages 中的临时推进过程
- 会话内 todo 状态
- 当前轮 reminder
可能跨请求继续存在的
- memory
- 持久任务图
- runtime task 输出
- worktree
- MCP 连接状态
所以你要逐渐学会区分:
query-scope state
session-scope state
project-scope state
platform-scope state
用一个完整例子串一次
还是用这个请求:
修复 tests/test_auth.py 的失败,并告诉我原因
系统可能会这样流动:
- 用户请求进入
QueryState - system prompt + memory + tools 被组装好
- 模型先调用
todo,写出三步计划 - 模型调用
read_file("tests/test_auth.py") - 工具路由到本地文件读取 handler
- 读取结果包装成
tool_result写回消息流 - 下一轮模型调用
bash("pytest tests/test_auth.py -q") - 权限系统判断这条命令是否可执行
- 执行测试,输出太长则先落盘并留预览
- 失败日志回到消息流
- 模型再读实现文件并修改代码
- 修改后再跑测试
- 如果对话变长,
s06触发压缩 - 如果任务被拆给子 agent,
s15-s17介入 - 最后模型输出结论,本次请求结束
你会发现:
整套系统再复杂,也始终没有脱离“输入 -> 动作意图 -> 执行 -> 结果写回 -> 下一轮”这条主骨架。
读这篇时最该记住的三件事
1. 所有模块都不是平铺摆在那里的
它们是在一次请求的不同阶段依次介入的。
2. 真正的闭环只有一个
那就是:
tool_result 回到 messages
3. 很多高级机制,本质上只是围绕这条闭环加的保护层
例如:
- 权限是执行前保护层
- hook 是扩展层
- compact 是上下文预算保护层
- recovery 是出错后的恢复层
- task/team/worktree/MCP 是更大的平台能力层
一句话记住
一次请求的完整生命周期,本质上就是:系统围绕同一条主循环,把不同模块按阶段接进来,最终持续把真实执行结果送回模型继续推理。