2.4 KiB
Agent Note: Python SDK 递归会话通知
Status: implemented
English | 中文
问题
Python SDK 过去通过将每条通知的 payload 与根会话 ID 直接比较来过滤轮次通知。直接子 agent 的生命周期通知因 parent ID 指向根会话而能够通过,但孙级生命周期通知与所有后代 session.event 都会被拒绝。JSON-RPC 服务器仍会发出这些通知,因此它们会堆积在底层全局队列中,而高层消费者会丢失嵌套轨迹的关系与结束状态。
决策
HarnessClient 会在分发通知前,记录每条有效 subagent.started 和 subagent.finished 所包含的 child-to-parent(子到父)关系。会话订阅会沿客户端生命周期内保存的祖先关系图回溯每个 payload 中的 session ID、parent ID 与 child ID,判断它们是否属于请求的根会话。该关系图会跨连续订阅保留,因此某个后代即使跨过一次 Session.run(),在后续轮次中发出通知时仍能正确归属;客户端启动新的运行时进程时会重置关系图。
Session.run() 通过 TurnResult.notifications 与 on_notification 提供已发现会话树的完整通知流。只有 sessionId 等于请求根会话的 session.event 才会进入 TurnResult.events 或参与最终回复重建。因此调用方能够观察后代事件,同时子会话回复不会覆盖根会话回复。
考虑过的替代方案
在每条 JSON-RPC 通知中加入根会话 ID。 服务器已经提供精确的直接父子关系;在线路协议中重复传递祖先关系,会迫使每个生产者承担客户端订阅状态的职责。
把 subagent 限制为一层。 部署可以设置 maxDepth: 1,但让 SDK 依赖该策略,会对合法的递归组合产生静默误报。
只订阅后代生命周期通知。 这可以修复关系与结束状态的上报,但后代会话事件仍会堆积在全局队列中,回调看到的会话树也不完整。
后果
高层消费者会按线上的原始顺序收到嵌套生命周期与会话通知,同时根轮次结果保持原有回复语义。客户端会为每个已观察到的子会话保留一条父关系,直到运行时重启;祖先回溯能够安全处理环,无关会话通知仍可从全局队列获取。无密钥 Python 测试覆盖两层派生、根回复隔离、会话树通知不堆积,以及跨订阅复用祖先关系。