流式取消要向下传播
Agent 的“停止生成”按钮不应该只是停止前端收 token,而要把取消信号一路传到正在跑的子图、工具和后台任务。LangGraph 1.2.6 修复了 v3 event streaming 里 stream.abort() 只关闭 mux、不关闭底层 graph iterator 的问题:用户界面看起来停了,但 astream / stream generator 和 running subgraphs 可能继续跑到完成,继续消耗模型调用、沙箱时间、数据库锁或外部系统配额。
这类 bug 的关键不是某个框架的流式 API 细节,而是 Agent runtime 的取消语义到底有没有“向下传播”。前端 abort、HTTP disconnect、审批拒绝、用户点击 stop,都应该被翻译成同一个可追踪的 cancellation path:关闭顶层 iterator,触发 GeneratorExit / aclose(),让 in-flight node、subgraph、tool wrapper 和资源清理 hook 都有机会收到信号。如果只在展示层停止 pump,后台执行就会变成幽灵任务,尤其在多 Agent graph、browser session、长工具调用和队列 worker 里很难排查。
工程上可以把取消当成和重试一样的一等协议:每个 run / step / tool call 带 cancellation token 或 run id;stream adapter 不只负责转发事件,还负责把 abort 映射到底层执行器的 close;测试里专门放一个 looping subgraph 或长 running tool,断言 abort 后它真的停止,而不是只是前端不再显示。
做 OPC 或 Agent 平台时,可以问一个很具体的问题:如果用户在第 3 秒点了停止,我们能证明第 4 秒之后没有任何子任务、浏览器动作、外部 API 或后台 workflow 还在替他继续执行吗?