DSH plugin 怎么跟 Agent 生命周期?turn/step 时序、状态与两类事件
Agent 生命周期最容易踩的坑,是把两套事件当成一套用:agent/* 是实时协调,session/event 是持久回放。 前者告诉你“现在在队列里、正在跑、该重试”;后者告诉你“历史上到底发生了什么”。写插件前先决定你要观察哪一类,否则会出现“实时能看到、回放却没有”的错觉。
DeepSeek Harness:一轮 turn 的时序
一次用户输入先进入 inbox,再由 driver 认领成 turn;turn 内可以跑多个 step。 主干顺序:(来源)
- followup(content) — 用户或上游把消息放进 inbox。预期:出现
agent/inbox/spliced与agent/inbox/inserted。 - turn/start — driver 被排队工作唤醒,状态变 running。预期:开始认领待处理的下一步输入与一条排队 prompt。
- system-prompt/assemble — 组装系统提示词。预期:waterfall 可以在这里改写提示词。
- agent/pre-step — 决定是否进入消息批次。预期:返回 reject 或 enter(messages)。
- step/start — 进入一个 step。预期:随后发生
agent/request、请求准备与消息准入。 - assistant/message 或 assistant/attempt — 记录成功调用或失败尝试。预期:
agent/assistant-stream先实时推送 chunk,再给 committed end。 - 工具执行 — 按 executionMode 分类,走 barrier 与有界滚动池。预期:
tool/call、工具结果事件、tool/result按序出现。 - step/end → turn/end — 没有下一步输入且自然停止时收尾。预期:状态回到 idle。
如果 pre-step 拒绝、第一批为空或 pre-step 失败,已认领的批次保持移除,打开的 turn 不消耗 step。这不是错误,而是“这一轮暂时没有可执行输入”。
DeepSeek Harness:agent/* 与 session/event 的分工
实时状态与持久事实是两条通道,消费错通道就会得到不完整的历史。 对照:(来源)
| 通道 | 内容 | 适合谁 |
|---|---|---|
agent/* | 队列、状态、请求构造、steering、错误处理 | UI、实时协调插件 |
session/event | turn/step、消息、工具调用与结果 | SDK transcript、回放、审计 |
官方明确建议:需要可回放 transcript 的 SDK 用户应消费 session/event。agent/* 不是历史记录,它服务于“现在怎么协调”。
实时 agent/assistant-stream 的 chunk frame 是瞬态数据;回放读取的是 assistant/message 或 assistant/attempt 里的持久 settlement。进程在 settlement 前硬中断,不会留下持久 attempt stream。
DeepSeek Harness:三个可介入点
插件不需要改 driver,只要选对钩子:pre-step 管准入,request-error 管溢出,turn-stopping 管收尾。 三个点:(来源)
agent/pre-step— 在构造请求前拦截或替换消息。预期:可以拒绝一批输入、补充上下文,或保留下游消息。agent/request-error— 处理规范上下文溢出与重试决策。预期:返回重试动作或保留原始错误;不要拿它做通用异常兜底。agent/turn-stopping— 自然停止且 inbox 为空时的串行终检。预期:适合做收尾检查,不要在这里启动新的长任务。
包装 next() 时要注意:保留下游消息与 startsRequestSeries,除非你确实想替换整批输入。
DeepSeek Harness:工具并发与 barrier
工具不是一把并发跑完;driver 会按 executionMode 分类,用 barrier 与有界滚动池控制节奏。 关键点:(来源)
- 先分类再启动 — 每个待处理调用按执行模式归类。预期:只读与写入不会无序混跑。
- 有序 pre、并发 execute、有序 post — 前置与后置按模型顺序,执行阶段可并发。预期:结果顺序仍与模型请求一致。
- 工具自有事件 — 工具可以在执行中写自己的事件。预期:这些事件不替代
tool/result。 - barrier 会重新分类 — 滚动池在启动前会再次检查。预期:不会因为状态变化绕过屏障。
写工具插件时,不要假设“上一个工具一定已经结束”;需要顺序就显式声明,而不是靠时间差。
DeepSeek Harness:三种消费方式
观察生命周期的方式不同,选错会多写很多胶水。 三种:(来源)
- UI 实时展示 — 消费
agent/status与agent/assistant-stream。预期:状态与流式输出及时。 - SDK transcript — 消费
session/event。预期:能回放完整 turn/step 与工具结果。 - 插件钩子 — 监听
agent/pre-step、agent/request-error、agent/turn-stopping。预期:在正确阶段介入,不破坏 driver 时序。
如果同一份数据在两套通道里不一致,以 session/event 为准做历史判断,以 agent/* 为准做实时协调。
DeepSeek Harness:一张事件顺序表
排查时序问题时,先把关键事件按顺序列出来,比读整段日志快。 简化顺序:(来源)
| 阶段 | 关键事件 | 说明 |
|---|---|---|
| 入队 | agent/inbox/spliced、inserted | 消息进入 inbox |
| 开始 | turn/start、agent/status running | driver 认领输入 |
| 准入 | system-prompt/assemble、agent/pre-step | 决定是否进入消息批次 |
| 请求 | step/start、agent/request | 准备并发出模型请求 |
| 结果 | assistant/message 或 assistant/attempt | 成功消息或失败尝试 |
| 工具 | tool/call、tool/result | 按 executionMode 调度 |
| 收尾 | step/end、turn/end、agent/status idle | 轮次结束 |
如果日志里缺少其中一段,不要先怀疑模型;先确认是不是被 pre-step 拒绝、被取消,或进程在 settlement 前中断。
三个排查判据
时序问题先看“缺哪一段”,比逐行读日志快。 三个判据:
- 有 turn/start 没有 step/start — 多半是 pre-step 拒绝、第一批为空或 pre-step 失败。预期:turn 不消耗 step,属于正常拒绝。
- 有 step/start 没有 assistant/message — 请求失败或被取消,可能留下
assistant/attempt。预期:按 request-error 与取消原因查。 - 有 tool/call 没有 tool/result — 工具还在执行、被 barrier 挡住,或进程中断。预期:看 executionMode 与活跃执行。
三个判据能把问题定位到准入、请求或工具层,而不是笼统地“Agent 不动了”。
DeepSeek Harness 常见问题
Q:为什么实时流里有内容,回放却没有? 实时 chunk 是瞬态的;回放只读 settlement。没有 settlement 的尝试不会留下持久流。
Q:turn/end 之后还会不会有 step? 不会。turn/end 是轮次终点;下一步输入会开新的 turn。
Q:压缩是在哪个阶段发生的?
基础压缩通过 agent/pre-step 处理压力,agent/request-error 只处理规范上下文溢出;先剪枝工具结果,再选择摘要。
一句话收束: 生命周期插件只要记住“实时看 agent/*、历史看 session/event、介入选对钩子”,就不会把协调状态当成审计记录。
常见问题
DeepSeek Harness 里,agent/* 是实时控制与状态,例如队列、状态、请求构造、steering 与错误处理;session/event 是持久回放事实,记录 turn、step、消息与工具结果。需要可回放 transcript 的 SDK 应消费 session/event。
DeepSeek Harness 里,一个 turn 可以包含多个 step。每个 step 对应一次模型请求与随后的工具执行;当 inbox 里还有下一步输入,或工具结果需要继续请求时,会在同一个 turn 里进入下一个 step。
DeepSeek Harness 里,被 claim 的批次保持移除,已经打开的 turn 不消耗 step;如果第一批为空或 pre-step 失败,同样不进入 step/start。监听器通过包装 next() 可以保留下游消息与 startsRequestSeries。
DeepSeek Harness 里,不适合。它主要用于规范的上下文溢出;压缩会先在 pre-step 处理压力,再在 request-error 触发时做工具结果剪枝与摘要。普通错误应按各自错误路径处理,不要都塞进这个钩子。
DeepSeek Harness 里,不能。agent/assistant-stream 的 chunk frame 是瞬态数据;回放读取 assistant/message 或 assistant/attempt 里的持久 settlement。进程在 settlement 前硬中断,不会留下持久 attempt stream。
相关术语
- turn
- turn 是 DeepSeek Harness 中一次用户输入驱动的完整轮次,从 turn/start 开始,到 turn/end 结束;一个 turn 可以包含多个 step。— DeepSeek Harness 官方参考 - Agent 轮次与步骤生命周期
- step
- step 是 turn 内的一次模型请求与工具执行单元,以 step/start 开始、step/end 结束;模型请求、消息准入与工具结果都在 step 内发生。— DeepSeek Harness 官方参考 - Agent 轮次与步骤生命周期
- agent/pre-step
- agent/pre-step 是 DeepSeek Harness 的 waterfall 钩子,在构造模型请求前决定是否进入消息批次;它可以拒绝或替换消息,拒绝时该批次不消耗 step。— DeepSeek Harness 官方参考 - Agent 轮次与步骤生命周期
- session/event
- session/event 是 DeepSeek Harness 的持久会话事件流,记录 turn、step、消息、工具调用与结果,是回放与 SDK transcript 的事实来源。— DeepSeek Harness 官方参考 - Agent 轮次与步骤生命周期
来源
- DeepSeek Harness 官方参考 - Agent 轮次与步骤生命周期· deepseek-ai
- DeepSeek Harness 官方参考 - 会话· deepseek-ai