# Recursive 任务协议 ## 文档维护规范 0. **代码是权威实现** - 本文档只记录 `AGENT_MODE=recursive` revision 2 已实现的协议;字段和门禁变更时需同步更新 1. **协议与投影分层** - `Trace.context.task_protocol` 是权威状态,Goal 状态只用于流程展示 2. **不扩展到 Legacy** - Legacy 仍使用自由文本 `task/summary` 和原 Goal 自动推进逻辑 --- ## 概述 Recursive 任务协议把本地父子 Agent 协作约束为: ``` 父 Agent 下发 TaskBrief → 子 Agent 执行并提交 TaskReport → 独立 Validator 生成 ValidationResult → 父 Agent 生成 TaskReview → 修订原孩子 / 创建新孩子 / 重新规划当前层 / 完成或失败 ``` 这套协议只用于本地 Recursive Agent。Recursive revision 2 不允许 `remote_*`;Legacy 和 Recursive revision 1 的远端路由不进入本协议。模式、深度、孩子配额、调度和资源预算见 [Agent 运行模式](./agent-modes.md)。 --- ## 协议数据 ### RootTaskAnchor:根任务锚点 | 字段 | 类型 | 规则 | |------|------|------| | `objective` | `string` | 必填,整棵任务树的根目标 | | `completion_criteria` | `string[]` | 必填且至少一项,也是根 Validator 的完成标准 | | `constraints` | `string[]` | 根级硬约束,自动进入每层 TaskBrief | 新建 Recursive 根 Trace 必须通过 `RunConfig.root_task_anchor` 或 REST `root_task_anchor` 提供。框架固化规范化内容和哈希,后代只读取根 Trace 权威副本;规范化后最多 4,000 字符。 ### TaskBrief:父级下发的任务说明 | 字段 | 类型 | 规则 | |------|------|------| | `objective` | `string` | 必填,子任务目标 | | `reason` | `string` | 必填,说明为什么拆出该任务 | | `completion_criteria` | `string[]` | 必填且至少一项 | | `expected_outputs` | `string[]` | 必填且至少一项 | | `parent_findings` | `string[]` | 父级已确认的发现,默认为空 | | `context` | `object` | 与本任务直接相关的显式上下文 | | `constraints` | `string[]` | 硬约束;自动继承父 TaskBrief 的约束,子级只能增加 | | `context_refs` | `ContextRef[]` | 当前父 Trace 已授权且明确转授的 `ref_id/version` | | `validation_scopes` | `evidence \| hypothesis \| output \| task` 数组 | 父级选择子任务验收维度;框架始终补上 `task` | TaskBrief 会去重、检查 JSON 可序列化性,规范化后最多 16,000 字符,并保存当前版本与历史版本。Recursive 本地 `agent()` 使用 `task_brief`,不接受 `messages`。 ### TaskReport:子级提交的执行报告 | 字段 | 类型 | 规则 | |------|------|------| | `child_trace_id` | `string` | 框架注入,必须等于当前子 Trace | | `summary` | `string` | 必填的执行总结 | | `outcome` | `satisfied \| partial \| failed \| protocol_error` | 任务结果 | | `validation` | `Validation` | 执行者自检,不是框架权威验收 | | `next_step_suggestion` | `object` | 子级建议,不直接创建父级的下一个孩子 | | `outputs` / `evidence` | `object[]` | 产出和证据 | | `artifact_refs` | `ArtifactRef[]` | 可由可信 Resolver 读取和校验的真实产物引用 | | `source_urls` | `string[]` | Evidence/Hypothesis Validator 可以直接打开的公开 HTTP(S) 来源 | | `remaining_issues` | `string[]` | 未解决问题 | `Validation` 只包含 `hard_passed` 和 `open_issues`。`outcome=satisfied` 时必须 `hard_passed=true`,且 `open_issues` 和 `remaining_issues` 都为空。 `next_step_suggestion.direction` 为 `DESCEND / REFINE / ASCEND / NONE`。`DESCEND/REFINE` 必须附带 `suggested_next_task`;该字段仅是建议,父 Agent 必须审核后才能执行。 ### ValidationPlan / ValidationResult:框架权威验收 `ValidationPolicy` 是信任应用注入并在根 Trace 固化的最低规则。框架将它与 TaskBrief、TaskReport、真实材料、轨迹 head、模型和工具策略编译为 `ValidationPlan`;`plan_hash` 覆盖这些输入,任一变化都必须整份重验。 Plan 中每个 `ValidationCheckSpec` 固定 `check_id/scope/criterion/method/required`。 每个 Scope 产生一份 `ScopeValidationResult`,内含逐项 `ValidationCheck(status=passed|failed|unknown)`。模型只能返回 Plan 中已有的 `check_id`;遗漏必选项、重复、新增、Scope 错误或伪造证据均使当前 Scope 变成 `error`。 最终 `ValidationResult` 包含 `evaluated_trace_id/outcome/scope_results/issues/retry_from/plan_hash`。 聚合优先级为 `error > failed > unknown > passed`;`failed/unknown` 有明确回退位置, `error` 的 `retry_from=null`。 ### TaskReview:父级的审核决定 | 字段 | 类型 | 规则 | |------|------|------| | `parent_trace_id` | `string` | 框架注入 | | `child_trace_id` | `string` | 必须是当前 Trace 的直接孩子,且 UID 一致 | | `decision` | `ReviewDecision` | 见下方决策矩阵 | | `reason` | `string` | 必填 | | `approved_next_task` | `TaskBrief \| null` | 批准的新建或修订任务 | | `retry_from` | `RetryFrom \| null` | 仅由框架从 `ValidationResult` 注入,不是公开工具参数 | --- ## 状态机与工具门禁 Goal 可视状态为: ``` pending → in_progress → waiting_children → pending_review ↓ in_progress / completed / failed ``` 1. 父 Agent 调用 `agent(task_brief=...)` 后,原 Goal 进入 `waiting_children`。 2. 子 Agent 必须先审核完自己的孩子、执行完已批准 action,再调用 `submit_task_report`。 3. 子报告经 Validator 处理后,父 Goal 进入 `pending_review`。 4. `pending_review` 期间运行时只暴露 `review_task_result` 和可用时的 `read_context_ref`,Goal 工具也拒绝新增、完成、放弃或切换。 5. 审核产生 next action 后,运行时只暴露 `agent` 和可用时的 `read_context_ref`,且实际 TaskBrief 必须与批准内容规范化后完全一致。 Recursive 禁止 GoalTree 自动切换下一个 pending sibling,也禁止所有孩子完成时级联完成父 Goal。父 Agent 必须在审核后自己决定。 --- ## 审核决策 ### 决策语义 | 决策 | 效果 | |------|------| | `ACCEPT_REFINE` | 接受建议,把 `approved_next_task` 加入父级 next action,由父级创建新的直接孩子 | | `REJECT_REFINE` | 不采纳子级建议;其他待审报告处理完后,父级恢复 `in_progress` | | `REVISE_CHILD` | 进入修订 action;下一次只能用 `continue_from` 续跑原直接孩子,不消耗新孩子名额 | | `DESCEND_AGAIN` | 批准一个新 TaskBrief,由当前父级再创建一个直接孩子 | | `REPLAN_CURRENT` | 待当前批次审核完后,恢复创建该孩子的原 Goal 为 `in_progress` | | `ASCEND` | 完成父级当前 Goal,不级联完成它的父 Goal,不自动进入兄弟 Goal | | `FAIL` | 将父级当前 Goal 标为 `failed`,不级联到更高层 | ### ValidationResult 决策矩阵 | Validator 结果 | 允许的决策 | |------------------|------------| | `passed` | `ACCEPT_REFINE` / `REJECT_REFINE` / `REVISE_CHILD` / `DESCEND_AGAIN` / `ASCEND` / `FAIL` | | `failed` | `REVISE_CHILD` / `REPLAN_CURRENT` / `FAIL` | | `unknown` | `REVISE_CHILD` / `REPLAN_CURRENT` / `FAIL` | | `error` | `REVISE_CHILD` / `FAIL` | 还有两层硬约束: - `TaskReport.outcome=failed/protocol_error` 只能选 `REVISE_CHILD/FAIL`。 - `ASCEND/FAIL` 只能审核本批最后一份待审报告,且不得留有未执行的 next action。 ### REPLAN_CURRENT 只回退直接父级 `REPLAN_CURRENT` 没有 `target_trace_id` 或 `ancestor_trace_id` 参数。回退目标由子 Trace 持久化的 `parent_trace_id` 和 `parent_goal_id` 确定: ``` 孙 Trace 验收失败 → 子 Trace 审核并 REPLAN_CURRENT → 只恢复子 Trace 中创建孙节点的 Goal → 如果需要更高层回退,子 Agent 先提交自己的 TaskReport → 父 Agent 再独立审核 ``` `retry_from` 来自当前报告的 `ValidationResult`,父 Agent 不能修改。 ### 批量报告 批量孩子各自产生 TaskReport、ValidationResult 和 TaskReview。父级必须逐份审核: - 只审核一部分时继续保持 `pending_review`。 - `REPLAN_CURRENT` 先记入 `pending_replans`,本批全部审核完才恢复目标。 - 本批后续选择 `FAIL` 会清除已记录的 replan。 - 已批准的新孩子还会预占每父六孩子配额,避免审核通过后才发现无名额。 --- ## 独立 Validator ### 子任务验收 `satisfied/partial` 报告按有效 Scope 顺序执行:`evidence → hypothesis → output → task`, 每个 Scope 创建独立 Validator Trace,一份 TaskReport 最终只产生一份聚合 ValidationResult 和一次父级审核。根固定只执行 `root`。`failed/protocol_error` 报告以及已停止孩子走确定性不通过路径,不浪费模型调用。 Validator Trace 的约束: - `created_by_tool="validator"`,`agent_type="validator"`。 - `parent_trace_id` 指向被验收的业务 Trace,`root_trace_id` 和 UID 保持一致。 - 不增加业务 `agent_depth`,不占每父六孩子和业务 Agent 预算。 - `output/task` 为单次无工具 LLM;`evidence/hypothesis/root` 可进入有轮次上限的受控 Agentic 循环,均使用 `temperature=0`。 - 调用计入整树 LLM、Token、成本和时间预算,并参与当前进程的子树停止。 - 不可 `continue_from`,不再生成 Validator。 Validator 输入由框架从 Policy、Plan、TaskBrief、TaskReport、RootTaskAnchor、 持久化主路径、真实 Tool Result 和已解析 Artifact 组装。固定协议和必需材料 优先保留,轨迹按最新消息优先裁剪,整体最多 50,000 字符;必需材料无法 完整进入时返回 `unknown`,不会截断后通过。侧分支和 `reasoning_content` 不进入验收。 RootTaskAnchor 也作为固定字段进入验收包。Validator 不会自动展开 ContextRef;只有业务 Agent 实际读取过的快照才会以 Tool Result 进入轨迹。 `evidence/hypothesis/root` 只能使用 Validator 私有的 `validator_web_search` 和 `validator_open_url`。页面读取只允许报告声明或本轮搜索返回的公开 HTTP(S) URL,逐跳校验 DNS 并固定已验证 IP,不携带 Cookie/Auth,不支持登录、点击、 JS、下载、PDF 或私网地址。网页正文始终标记为不可信材料;Evidence 通过时 `evidence_refs` 必须指向当前 Validator Trace 真实打开的 source ID。 Validator 默认继承被验收 Agent 的模型,可用 `AGENT_VALIDATOR_MODEL` 覆盖; 根可再用 `AGENT_ROOT_VALIDATOR_MODEL` 单独覆盖。模型输出非法、越权工具调用或轮次超限 直接生成 `outcome=error`,不发起格式修正调用。同一 `plan_hash` 在重启后可直接 恢复已完成 Scope;任一权威输入改变都整份重验。 ### 真实产物 `outputs/evidence` 是执行者声明,不能单独证明交付存在。`ArtifactRef` 只保存 `artifact_id/version/content_hash/kind/mime_type`;应用通过可信、只读 `ArtifactResolver` 将它解析为真实材料。明确缺失或 hash 不符为 `failed`,解析器 暂不可用为 `unknown`,跨 root/UID 或结构伪造为 `error`。框架不提供任意本地路径读取。 ### 根任务完成门禁 新建 Recursive 根 Trace 必须显式提供 `root_task_anchor`。根 Agent 生成无 Tool Call 的候选答案时,框架使用 Anchor 中的根标准、候选答案和持久化主路径运行 `scope=root` 的 Validator: - 通过:根 Trace 才可写为 `completed`。 - 第一次未通过或 Validator 错误:将框架生成的 ValidationResult 追加到根消息,允许修正一次。 - 第二次仍未通过:根 Trace 写为 `failed`。 - Validator 异常、停止或预算不足都不会绕过完成门禁。 --- ## 失败、停止、续跑与回溯 - 非根 Agent 没有合法 TaskReport 时,框架最多注入两轮纠正提示;仍未提交时生成 `protocol_error` 报告并失败结束。 - 子 Agent 异常或无有效报告时,父级依然会收到框架生成的报告和 ValidationResult,不会跳过审核。 - 停止的子 Agent 生成 `outcome=failed` 的 TaskReport;父级只能选择 `REVISE_CHILD` 或 `FAIL`。 - `REVISE_CHILD` 把旧报告移入 `report_history`,清空当前报告和 Validator 缓存;续跑后必须再提交新报告。 - 服务重启后,`pending_reviews` 和 `next_actions` 从 Trace context 恢复。 - 回溯会按 sequence 删除截断点之后的报告、审核和 action,恢复被回溯的待审报告,重建 `pending_replans` 和 Goal 状态投影。 - 回溯、停止和续跑都不退还已消耗的树级资源。 --- ## 持久化状态 `Trace.context.task_protocol` 保存: ```text task_brief task_brief_version / task_brief_history task_report task_report_submitted_at_sequence task_report_validation report_history pending_reviews reviews next_actions pending_replans root_validation_attempts root_validation_history root_validation_passed protocol_correction_attempts ``` `Trace.context.context_access` 另存当前 Trace 被授权的不可变快照与字符用量;该目录不并入 `task_protocol`。引用的生成、转授、读取和限额见 [Context 管理](./context-management.md#contextref可逐层转授的完整协议引用)。 `pending_reviews` 的每一项同时保存 TaskReport、ValidationResult、原 Goal ID 和接收 sequence。GoalTree 不是这些协议事实的权威存储。 --- ## 实现与测试 | 内容 | 位置 | |------|------| | 数据模型和协议状态 | `cyber_agent/core/task_protocol.py` | | RootTaskAnchor、TaskBrief 版本与 ContextRef | `cyber_agent/core/context_policy.py` | | `read_context_ref` | `cyber_agent/tools/builtin/context.py` | | `submit_task_report` / `review_task_result` | `cyber_agent/tools/builtin/task_protocol.py` | | ValidationPolicy、Plan、Scope 执行与聚合 | `cyber_agent/core/validation.py` | | 受控搜索、URL 边界和 Serper 适配 | `cyber_agent/core/validator_web.py` | | ArtifactRef 与 ArtifactResolver 窄接口 | `cyber_agent/core/artifacts.py` | | 运行时门禁、根 Validator、回溯恢复 | `cyber_agent/core/runner.py` | | 子报告汇合和 Validator 触发 | `cyber_agent/tools/builtin/subagent.py` | | Goal 状态与变更门禁 | `cyber_agent/trace/goal_models.py` / `goal_tool.py` | 主要测试: - `tests/test_task_protocol.py` - `tests/test_recursive_replan_context.py` - `tests/test_recursive_validation_core.py` - `tests/test_recursive_validator_web.py` - `tests/test_recursive_validation_artifacts.py` - `tests/test_recursive_validator_lifecycle_complex.py` - `tests/test_recursive_runtime_extensions.py`