delegate task用asyncio.shield保护in-flight工具调用不被取消打断(issue #189 grill定案) #189

Open
opened 2026-08-21 03:25:57 +00:00 by KumaAgent · 0 comments
Member

来源

全量32条ADR设计合理性对抗审查(评估侧内部执行,2026-08-21,组G)grill定案。完整推理链条见 ADR-0020 2026-08-21(issue #189 grill)更新节。

结论

asyncio.shield() 保护正在执行中的工具调用,不被 task.cancel() 从中打断。

核实确认:DelegatedTaskRegistry.cancel()delegate_task.py:75)调用真正的 asyncio.Task.cancel(),可在 subagent.py::run_delegated_task 循环体内任意 await 点(含 call_host_tool 工具调用执行中途)抛出 CancelledError,没有协作式检查点。子智能体工具集完全由host通过 get_tools 注入,零host接入意味着当前实际工具集是空集,ADR-0019"给用户加道具"这类副作用工具目前纯属假设性举例——但 issue #188(已合并)新增的"真人活跃"自动抢占大概率复用同一条取消路径,且不经模型识别、drive_tick周期性运行暴露窗口更大,"取消撞上工具调用执行中"这个场景的触发概率会实质性上升——现在就把保护机制设计好,不等真实副作用工具出现。

What to build

subagent.py::run_delegated_task 第145行:

context.append(await call_host_tool(call.id, tool, call.arguments))

改为:

context.append(await asyncio.shield(call_host_tool(call.id, tool, call.arguments)))

task.cancel() 触发时,CancelledError 在这个await点仍会立刻传给外层循环(循环/任务整体正确识别取消、停止继续),但被shield保护的 call_host_tool(...) 协程本身会在后台跑完,不会被从中打断——确保副作用(若有)完整生效而非半途而废。取消发生时该次工具调用的返回值不会被写入context/不影响蒸馏结果,只保护副作用执行完整,不保证结果被使用。

核心收益:不需要host配合(工具不需要标记"是否有副作用",与 tool_port.py "core不理解工具语义"的既有哲学一致),也不需要重新设计取消入口(cancel_delegate_task 与 issue #188 的自动触发都不用改)。

Acceptance criteria

  • subagent.py::run_delegated_taskcall_host_tool 调用改用 asyncio.shield() 包裹
  • 补测试:模拟一次耗时较长的工具调用执行期间被 task.cancel() 打断,断言该工具调用本身完整跑完(不是被中途abort),但外层 run_delegated_task 正确抛出/传播 CancelledError、不再继续下一轮
  • 补测试:确认取消发生在其它await点(llm_client.complete() 调用期间)时行为不变(不需要shield保护,因为那里没有外部副作用)
  • 确认 call_host_tool 内部若真实抛出非取消类异常(工具调用失败),asyncio.shield 不影响既有"失败即一次普通tool_response"的处理逻辑(回归测试)
  • ADR-0019/0020 补更新节记录具体实现
  • 全量测试通过

Not in scope

  • 不改其它await点(llm_client.complete() 两处)的取消行为——那两处没有外部副作用,不需要保护
  • 不新增"工具是否有副作用"的标记/元数据系统——asyncio.shield 对全部工具调用一视同仁,不需要区分
  • 不改 cancel_delegate_task 工具本身或 issue #188 的自动抢占触发逻辑——本票只改工具调用被中断时的行为,不改"何时触发取消"
## 来源 全量32条ADR设计合理性对抗审查(评估侧内部执行,2026-08-21,组G)grill定案。完整推理链条见 [ADR-0020](https://code.srcz.one/ProjectKuma/arise/blob/main/docs/adr/0020-deep-task-delegation.md) 2026-08-21(issue #189 grill)更新节。 ## 结论 **用 `asyncio.shield()` 保护正在执行中的工具调用,不被 `task.cancel()` 从中打断。** 核实确认:`DelegatedTaskRegistry.cancel()`(`delegate_task.py:75`)调用真正的 `asyncio.Task.cancel()`,可在 `subagent.py::run_delegated_task` 循环体内任意 await 点(含 `call_host_tool` 工具调用执行中途)抛出 `CancelledError`,没有协作式检查点。子智能体工具集完全由host通过 `get_tools` 注入,零host接入意味着当前实际工具集是空集,ADR-0019"给用户加道具"这类副作用工具目前纯属假设性举例——但 [issue #188](https://code.srcz.one/ProjectKuma/arise/issues/188)(已合并)新增的"真人活跃"自动抢占大概率复用同一条取消路径,且不经模型识别、drive_tick周期性运行暴露窗口更大,"取消撞上工具调用执行中"这个场景的触发概率会实质性上升——现在就把保护机制设计好,不等真实副作用工具出现。 ## What to build `subagent.py::run_delegated_task` 第145行: ```python context.append(await call_host_tool(call.id, tool, call.arguments)) ``` 改为: ```python context.append(await asyncio.shield(call_host_tool(call.id, tool, call.arguments))) ``` `task.cancel()` 触发时,`CancelledError` 在这个await点仍会立刻传给外层循环(循环/任务整体正确识别取消、停止继续),但被shield保护的 `call_host_tool(...)` 协程本身会在后台跑完,不会被从中打断——确保副作用(若有)完整生效而非半途而废。取消发生时该次工具调用的返回值不会被写入context/不影响蒸馏结果,只保护副作用执行完整,不保证结果被使用。 **核心收益**:不需要host配合(工具不需要标记"是否有副作用",与 `tool_port.py` "core不理解工具语义"的既有哲学一致),也不需要重新设计取消入口(`cancel_delegate_task` 与 issue #188 的自动触发都不用改)。 ## Acceptance criteria - [ ] `subagent.py::run_delegated_task` 的 `call_host_tool` 调用改用 `asyncio.shield()` 包裹 - [ ] 补测试:模拟一次耗时较长的工具调用执行期间被 `task.cancel()` 打断,断言该工具调用本身完整跑完(不是被中途abort),但外层 `run_delegated_task` 正确抛出/传播 `CancelledError`、不再继续下一轮 - [ ] 补测试:确认取消发生在其它await点(`llm_client.complete()` 调用期间)时行为不变(不需要shield保护,因为那里没有外部副作用) - [ ] 确认 `call_host_tool` 内部若真实抛出非取消类异常(工具调用失败),`asyncio.shield` 不影响既有"失败即一次普通tool_response"的处理逻辑(回归测试) - [ ] ADR-0019/0020 补更新节记录具体实现 - [ ] 全量测试通过 ## Not in scope - 不改其它await点(`llm_client.complete()` 两处)的取消行为——那两处没有外部副作用,不需要保护 - 不新增"工具是否有副作用"的标记/元数据系统——`asyncio.shield` 对全部工具调用一视同仁,不需要区分 - 不改 `cancel_delegate_task` 工具本身或 issue #188 的自动抢占触发逻辑——本票只改工具调用被中断时的行为,不改"何时触发取消"
KumaAgent changed title from 占位标题-稍后回填-11 to 评估:task.cancel()可能中断已生效副作用工具调用(ADR-0019/0020,全ADR对抗审查组G⑥) 2026-08-21 03:29:02 +00:00
KumaAgent changed title from 评估:task.cancel()可能中断已生效副作用工具调用(ADR-0019/0020,全ADR对抗审查组G⑥) to delegate task用asyncio.shield保护in-flight工具调用不被取消打断(issue #189 grill定案) 2026-08-21 05:04:29 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ProjectKuma/arise#189
No description provided.