Skip to content

Latest commit

 

History

History
34 lines (21 loc) · 5.8 KB

File metadata and controls

34 lines (21 loc) · 5.8 KB

Agent Note: 被委派的 subagent 以钉定为 'never' 的审批策略运行

Status: implemented

English | 中文

问题

被委派的子 agent 发起审批请求时无人可问。在交互式父级('ask')之下,后台子 agent 的升级请求会变成一个任何产品界面都不展示的挂起问题——subagent 会话不进入 Web 侧边栏,父级的 list_agents 只报告普通的 runningidle,目录树的行也只显示活动状态——因此被权限拦住的子 agent 与正常干活的子 agent 无法区分;headless 与无应答者的组合则让同一次 ask 以 'unavailable' 失败关闭。拒绝的审计记录只落在子 agent 自己的日志里,而且没有任何工具参数或 Web 控件能调整一个正在运行的子会话的沙箱模式或审批策略(Issue #1723)。机制繁重的修复方案——持久化的受阻状态投影、父级通知、目录树徽标,以及穿过 subagent 所有权围栏的权限写入路径——在临近发布时代价不成比例。

决策

被委派的子 agent 只在委派时固定的权限范围内行动,审批提示则从它的世界中彻底移除:captureDelegatedPolicyOverrides(parent)dsh-subagent/src/child-agent.ts)仍对父会话的显式沙箱覆盖项建立快照,但只要审批能力已组合,就把 approvalPolicy: 'never' 钉定下来——不再读取父级自身的审批策略。appendDelegatedPolicyOverrides() 把这个钉定作为持久化的 approval/policy { policy: 'never', source: 'delegation' } 事件写入子 agent 的日志,与沙箱快照走完全相同的一次性与可继续委派路径,因此冷恢复会重放它,fork 种子中陈旧的父级策略也会输给它。

强制执行沿用既有的 ApprovalService 'never' 语义,落在裁决 ask 的唯一操作上:子 agent 的每次 ask——bash 或 fs 的 sandbox_permissions 升级、hook 驱动的权限询问、任何未来的请求方——都在咨询任何应答者之前确定性地解析为 'rejected',同时仍在子日志上留下 approval/askedapproval/decided 审计对。子 agent 的全部权限故事因此就是它的沙箱范围:danger-full-access 父级委派出的子 agent 无需任何审批,read-only 父级委派出的子 agent 没有任何逃生通道,而放宽的决定始终属于父级一侧(先放宽父会话,再重新委派或继续 follow-up)。

每个进程内子 agent 都被告知而非被困住:applyChildComposition 注册作用域内的 subagent:delegation 运行时上下文声明(order 120,位于 sandbox:policyapproval:policy 语句之后),声明权限范围已在启动时固定、需要审批的操作会被自动拒绝、需要更宽访问的任务应以上报限制收尾而不是重试。该声明是运行时上下文贡献而非系统提示词 section,因此部署的系统提示词在父子之间保持统一(快照测试套件钉住了这一统一性),该事实也随策略语句乘坐同一份持久化快照。

本决策取代进程内委派策略决策中的审批一半,并推翻其「强制 'never' 会排除未来的子 agent 应答器」的结论:审批继承已经落地,产生的正是上述不可见的受阻状态;未来若要引入子 agent 应答器,必须先推翻本 note。

考虑过的替代方案

  • 继承父级的审批覆盖项(先前的行为):不予采纳。只有已处于 'never' 的父级才产生确定性的子 agent;交互式父级种出的子 agent,其 ask 要么等待一个无人在看的提示,要么以 'unavailable' 失败关闭,结果取决于当时恰好接入了哪些界面。
  • 受阻状态可见性与逐子级权限调整(#1723 原有的验收):延后而非否决。list_agents 的受阻标注、经由结算投递 seam 的父级通知、目录树徽标,以及 subagent 专用的权限通道仍是更完整的设计,但每一项都需要独立的 seam 工作;一旦子 agent 不可能进入等待审批的受阻状态,这些都不再是必需。
  • 把子 agent 的 ask 路由到父控制器:仍按审批 seam Agent Note 延后。它需要父链所有权与发起 spawn 的 callId
  • ApprovalService 内按会话来源钉定:不予采纳。这会让审批包耦合委派词汇,并重复一个委派边界已经拥有的决定;委派种入的事件之所以可强制执行,是因为当前不存在任何能切换子会话策略的写入路径(/permission 命令要求通用 Host 路由,而 subagent 所有权围栏对子会话拒绝该路由)。

后果

  • 子 agent 的沙箱继承就是委派权限模型的全部;DelegatedPolicyOverrides.approvalPolicy 字段收窄为 'never' | undefined(仅在未组合审批能力时为 undefined)。
  • 模型可见:每个子 agent 的运行时上下文快照携带 subagent:delegation 声明以及固定的审批已禁用语句;父级请求不变。executor 边界测试证明:即使根部有一个本会批准的应答者,子 agent 的升级仍被拒绝且不咨询该应答者,审计对照常落日志。
  • 边界:进程内一次性、可继续以及 workflow 派生的子 agent 都经由共享辅助函数强制执行;subagent-acp 子 agent 保留该提供方显式的机器 permission 策略;claude-codecodexdsh-sdk 子 agent 运行在外部进程中,由各自的组合决定。
  • 在钉定之前持久化的子 agent 冷恢复时折叠到部署审批默认值;处于预发布阶段,不添加迁移。
  • 快照夹具记录了该钉定:每个进程内子日志都新增委派 approval/policy 事件,subagent-published-run-failure 现在会持久化一份单事件子日志,而此前该子 agent 不留任何持久化事件。