日志
Logging 这个“Stage”存在,是为了让 Agent 在关键节点留下可追踪的痕迹:现在走到哪了、为什么分支、哪里出错了、是否快撞上限制。它不是一段独立主流程,而是一个横切层:从 stage-1 建立运行环境开始,一直跟着主循环、异常分支、subagent(被主 Agent 调用的小 Agent)过程,直到一次运行结束。
- 先记“起点和边界”
这层最早在 stage-1 就开始出现,比如建日志目录、提醒
max_turns(最多轮数)配置偏紧。 这说明它的职责不是推动业务往下走,而是给整次 run 打标签:这次怎么开始的,有哪些风险。 - 正常路径里,它负责记“流程标记”
在主循环的正常分支里,某些关键事件会打日志。 典型例子有:stage-4.2 里准备主动 summarize(把过长上下文压缩成摘要)时,会先记一条,告诉你“不是 LLM 突然答成这样,而是系统主动在收拾上下文”。 side-S1 里 subagent 开始、推进、结束时也会记进度标记。 这些日志不改变决策,但会把“系统为什么突然切换动作”解释清楚。
- 异常路径里,它负责记“失败原因”
_query_llm()(向 LLM 发起一次请求并处理结果)里几乎每个异常分支都会打 warning 或 error。 这里很关键,因为 LLM 调用失败有很多种:超时、返回坏格式、上游服务报错、重试耗尽。 如果没有这层记录,你只能看到“这一轮没继续”,却不知道是模型问题、网络问题,还是上下文问题。 - 特殊事件里,它负责记“为什么被迫停下”
例如 stage-4.1 里会记录 session death(终端会话已死,没法继续复用)的消息。 这类日志的价值在于把“系统停了”变成“系统因为什么条件停了”。 对排障的人来说,这比知道函数名有用得多。
- 它为什么必须散落在各处
因为日志不是一个能独立跑完的步骤。 它只能贴着真正的决策点、异常点、切换点去记。 如果把它集中到某个单独 Stage,很多最有价值的信息就已经错过了:异常栈只在异常发生那一刻最完整,分支原因也只在分支被选中的那一刻最清楚。
- 删掉会怎样
系统大概率还能跑。 但一旦出现“为什么突然 summarize”“为什么 subagent 卡住”“为什么 LLM 请求不断失败”“为什么终端会话失效”这类问题,你几乎没有现场。 也就是说,它不直接产出答案,但它直接决定系统是否可调试、可运营、可维护。
- 写: 无 — 依据给定 skeleton,这个 crosscut-X3 未被任何 register 显式提及;描述里也只指向
self.logger调用,没有对应的内部状态寄存器写入 - 读: 无 — 源信息只表明日志语句伴随各 Stage 的条件分支与异常处理出现,没有显示读取某个 register 作为本 Stage 的独立输入
- 清: 无 — 未给出任何由 Logging 专门清理的 register;日志本身是旁路记录,不承担状态复位
- 触发下游:
subsys-tmux-internal Tmux internal helpers— 无直接触发关系;这是横切关注点,在各主/侧分支内伴随运行,记录完后控制流回到原来的调用点,再继续进入后续实际 Stage
与前后 Stage 的衔接
上游 crosscut-X2 Output Length Limiting 控制“输出别太长”,而 Logging 不改这个结果,只把限制命中、警告或相关分支记下来。下游 subsys-tmux-internal Tmux internal helpers 是 tmux(可远程控制的终端)内部辅助逻辑;Logging 不给它产出业务数据,只是在这些辅助逻辑前后补充可追踪信息。