Skip to main content
agent 的一次回复可能内部跑了十几轮:调模型、跑工具、把结果喂回去、再调模型。 你只看得到最后那段话。中间哪一步慢了、哪个工具失败了三次、模型为什么决定换条路, 默认全是黑盒。 循环视图就是把这个黑盒打开。它在右侧面板里,与「链路追踪」并列, 入口在会话标题旁的更多菜单 → 循环。

两个视角,别混淆

同一个会话的同一份数据,两种切法: 排查性能看链路追踪,排查行为看循环。

迭代带怎么读

每一轮循环是一条迭代带:
带头那行是模型自己写的意图——取它这一轮回复的首句。这是整个视图里最值钱的一层: 它直接告诉你模型打算干什么,而不是让你从工具名去猜。上面那条就是模型原话 「确认是 4.18.2,把它提到 ^4.21.0 再装」。 每行一个步骤,右侧时间条按耗时定宽、按 atMs 定位,所以横向能直接比出快慢。 失败行整行染红(exit 127 这类退出码直接标在行上),重试行染琥珀。 迭代之间的箭头是回喂边,标注了喂回模型的内容摘要。这是循环的骨架—— 瀑布图里看不出这条边。 子代理以缩进形式嵌在派发它的那一轮里,父 run 的迭代计数含子 run。

四层 token 读数

上下文逐轮增长是长任务成本的主驱动,所以 token 分四级给: 缓存命中单独标绿,因为它是不重复计费的那部分。

终止归因

底部那条回答「循环为什么停在这」: 前五项在采集时就区分开了:用户取消与模型报错在底层是两回事,混在一起会让 错误率失去意义。

长时间任务:跑着就能看

迭代是逐轮落盘的,所以任务还在跑的时候,迭代带就一条条往外长 (有在途工具时每 2 秒刷新一次),不必等它跑完。 这依赖一个刻意的取舍:轨迹在每一轮结束时写一次盘,而不是等整个 run 结束。 轮级写入的频率是一次迭代一下,与 token 无关——流式输出的热路径上依然零 IO。

进程崩了还能看到什么

这是轨迹唯一的崩溃兜底。 如果 sidecar 在任务中途被杀,那次运行在内存里的完整树会丢。但因为迭代是逐轮落盘的, 下次启动会把它抢救回来:面板上出现一条标注「意外中断」的运行, 包含崩溃前所有已闭合的轮次。 边界要说清楚:丢的是当前正在跑的那一轮。比如崩在一次长命令执行中间, 那一轮不会出现——它的工具还没有结果。已经跑完的轮次一轮不少。 (崩溃前对话的消息内容另有转录兜底,所以不会连聊到哪都丢。丢的是时序与归因结构。)

筛选

一个长会话可能有几十轮、上百个步骤,靠滚是找不到东西的。
  • 只看失败:一刀切到所有失败、重试与进行中的步骤
  • 按工具名筛:点工具名按钮收窄(可叠加「只看失败」)
右上角实时显示命中比例(如 13/118 步)。切换运行会自动清空筛选。

数据与分辨率

轨迹落在会话数据目录下的 traces/<sessionId>.jsonl,一行一个完整的运行。 在飞的运行走 traces/<sessionId>.live.jsonl,按轮追加。
需要知道的几个截断与取舍:
  • 请求上下文与工具出参都是截断保存的。轨迹是元数据视图,不是转录的副本。 工具失败时的输出保留得更多(stderr 是诊断核心),成功时截得更紧。
  • 超长运行的早期轮次会丢弃正文。单次运行保留的正文总量有上限,超出后从 最旧的轮次开始释放——最新的那次请求才是你要看的。此时点开早期轮次, 结构、耗时、状态都还在,只是「请求上下文」为空。这是为了让内存不随运行长度 无限增长。
  • 没有 token 级直播。视图的粒度是「一轮」,看不到正在流式输出的字。

下一步

Agent 引擎

循环背后的机制:模式、权限、压缩、子代理。

子代理

一次派发出去的并行任务,在循环视图里是缩进的嵌套运行。