agent-modes.md 13 KB

Agent 运行模式

文档维护规范

  1. 先改文档,再动代码 - 新功能或重大修改需先完成文档更新、并完成审阅后,再进行代码实现;除非改动较小、不被文档涵盖
  2. 文档分层,链接代码 - 重要或复杂设计可以另有详细文档;关键实现需标注代码文件路径;格式:module/file.py:function_name
  3. 简洁快照,日志分离 - 只记录最重要的、与代码准确对应的或者明确的已完成的设计信息,避免推测、建议或大量代码;决策依据或修改日志若有必要,可在 docs/decisions.md 另行记录

概述

AGENT_MODE 决定新建根 Trace 使用哪种本地 Sub-Agent 语义:

模式 定位
legacy 保留旧的一层 Sub-Agent 行为,默认模式
recursive 启用受深度、孩子数、工具权限、审核和资源预算约束的递归任务树

AGENT_RECURSION_ENABLED 已删除;环境中仍存在该变量时会报错,不会静默兼容。

实现cyber_agent/core/agent_mode.py:AgentPolicycyber_agent/core/agent_mode.py:policy_from_environment


模式选择与固化

新建根 Trace 会在任何 LLM 调用前读取 AGENT_MODE;未设置时默认为 legacy,非法值直接拒绝创建。选定后,根 Trace 将以下字段写入 context

{
  "agent_mode": "recursive",
  "agent_mode_revision": 2,
  "agent_depth": 0,
  "root_trace_id": "<root-trace-id>"
}

本地子孙继承该持久化策略;续跑、回溯或服务环境变更不会改变已有任务树的模式。没有模式字段的历史 Trace 按 legacy 续跑并补写模式。

Recursive revision 2 的新根 Trace 必须同时具备 RootTaskAnchor、其内容哈希和预算快照。缺少这些必需数据的早期实验 Trace 不会自动升级,续跑时会要求重新创建任务。

实现cyber_agent/core/runner.py:AgentRunner._prepare_new_tracecyber_agent/core/runner.py:AgentRunner._prepare_existing_trace


能力边界

能力 Legacy Recursive revision 2
本地 Agent 深度 根为 depth 0,只允许 depth 1 根为 depth 0,允许 depth 1~5
每个父 Trace 的本地直接孩子 无数量配额 累计最多 6 个
子 Agent 再调用 agent 禁止 depth 1~4 且父级拥有 agent 时允许
任务参数 task / messages 本地委派必须使用 task_brief
任务结束 自然语言 summary 报告、独立验收和父级审核门禁
Goal 推进 保留自动切换 sibling 和父级级联完成 孩子返回后由父级重新审核与规划
批量孩子 整批并行 默认串行,可显式开启最多 2 并行
停止 当前 Trace 当前进程内的当前 Trace 及其本地后代
树级资源预算 不启用 可配置,默认启用

Recursive 的 5 层和 6 孩子只统计 agent 工具创建的本地业务 Trace。已创建后失败或停止的孩子仍占直接孩子名额;continue_from 续跑原孩子不新增名额。批量请求会先检查整批数量,超限时整批拒绝。

Legacy 和 Recursive revision 1 的 remote_* 调用保留原来的 task/messages 接口,不计入本地深度和孩子配额。Recursive revision 2 稳定拒绝 remote_*,避免远端路由绕过结构化任务、树级预算与审核门禁。

实现cyber_agent/tools/builtin/subagent.py:_run_agents


Recursive 运行流程

父 Agent 规划任务
  → 使用 TaskBrief 创建孩子
  → 孩子执行,必要时继续向下委派
  → 孩子提交 TaskReport
  → 独立 Validator 验收持久化轨迹
  → 父 Agent 审核并决定修订、重新规划、继续拆分或完成
  → 根 Agent 的候选答案通过根 Validator 后才能完成

本文档只定义运行模式和边界。TaskBrief、TaskReport、TaskReview、Validator、Goal 状态机和逐级回退见 Recursive 任务协议


工具权限

Recursive 子级的基础能力是下列集合的交集:

父级本次运行实际有效工具
∩ 当前 ToolRegistry 已注册工具
∩ Recursive 子级允许工具
∩ 当前深度允许工具

evaluatebash_command 不会授予 Recursive 子级;agent 只能在父级实际拥有且子级未到 depth 5 时继承。read_context_ref 同样只能逐层继承,depth 5 可以继续读取已授权引用。协议工具还会按 pending_review、已批准下一任务、是否根 Trace 等当前状态动态收紧。

权限同时作用于模型可见 Schema 和 ToolRegistry.execute() 的运行时 dispatch;即使伪造未暴露的 Tool Call,也会在参数注入和函数调用前被拒绝。内部权限快照由 Runner 注入,自定义 context 不能覆盖。

实现cyber_agent/core/runner.py:AgentRunner._get_runtime_tool_namescyber_agent/tools/builtin/subagent.py:_get_allowed_toolscyber_agent/tools/registry.py:ToolRegistry.execute


批量调度

Recursive 默认使用:

RunConfig(
    child_execution_mode="sequential",
    max_parallel_children=2,
)

child_execution_mode="parallel" 时,单次 agent(task_brief=[...]) 通过 semaphore 限制同时运行数,max_parallel_children 必须为 1~2。该上限只约束单批本地孩子,不是整棵树的全局并发器。无论完成顺序如何,汇合结果保持输入顺序。

Legacy 忽略这两个配置字段,保留原有批量并行。

实现cyber_agent/core/agent_mode.py:validate_recursive_child_executioncyber_agent/tools/builtin/subagent.py:_run_agents


停止传播

Recursive 在当前 Python 进程内登记活跃和排队的父子 Trace。停止一个 Trace 时:

  • 停止信号传递给它当前已登记的所有后代。
  • 停止子 Trace 不影响父级和兄弟。
  • 排队但尚未调用模型的孩子不会启动模型调用。
  • 不强制中断已在进行的 HTTP/LLM 请求;请求返回后不再执行其 Tool Call 或发起下一轮。

运行登记仅存于当前进程,不是持久化、跨 Worker 的取消机制。

实现cyber_agent/core/runner.py:AgentRunner.stopcyber_agent/core/runner.py:AgentRunner.request_stopcyber_agent/core/runner.py:AgentRunner.register_recursive_child


Context 继承边界

Recursive 孩子只获得当前任务必需的明确输入:

  • 规范化 TaskBrief 及从父 TaskBrief 继承的硬约束。
  • 从根 Trace 读取的不可变 RootTaskAnchor。
  • 当前 Trace 本地已授权的最多 8 个 ContextRef 快照;深层获取祖先结论必须逐边转授。
  • parent_trace_id / root_trace_id / agent_depth 等 Trace 血缘。
  • 冻结的工具能力快照和调度策略。
  • 任务协议状态和预算所属根 Trace。

不自动继承父 Agent 的完整消息历史、未筛选 Tool Result、父 Runner 的全部 config.context、内部运行对象或祖先 GoalTree。parent_findings、普通 context 和 ContextRef 也不会自动累积;引用需逐层重新下发。完整规则见 Context 管理

实现cyber_agent/core/context_policy.py:normalize_task_briefcyber_agent/core/context_policy.py:task_briefs_matchcyber_agent/core/runner.py:AgentRunner._build_tool_context


树级资源预算

Recursive 新根 Trace 会从环境变量读取一次预算,并把不可变快照保存到根 Trace context。Legacy 不解析这些预算变量。

环境变量 默认值 含义
AGENT_RESOURCE_BUDGET_ENABLED true false 时不执行限额,仍保留用量记录
AGENT_MAX_TOTAL_AGENTS 50 根 Agent 和本地业务子孙总数
AGENT_MAX_LLM_CALLS 150 本地 Agent 与 Validator 的模型调用总数
AGENT_MAX_TOTAL_TOKENS 1500000 输入和输出 Token 总数
AGENT_MAX_TOTAL_COST_USD 15 累计模型成本(美元)
AGENT_MAX_DURATION_SECONDS 3600 从根用量初始化开始的最长时间
AGENT_MAX_VALIDATION_TOOL_CALLS 300 受控 Validator 搜索和页面读取总次数
AGENT_MAX_VALIDATION_MATERIAL_CHARS 1000000 Validator 解析的产物、搜索结果和页面正文字符总数
AGENT_RESERVED_FINAL_CALLS 8 仅保留给根 Validator 的末尾调用数

所有数值必须为正数,且 AGENT_RESERVED_FINAL_CALLS < AGENT_MAX_LLM_CALLS。预算动态用量保存在根 Trace 目录的 resource_usage.json,记录 Agent、LLM、Token、成本、起始时间和最后拒绝原因。

关键计数语义:

  • Validator 不计入 Agent 数,但计入 LLM、Token、成本、时间、受控工具调用和验收材料字符数;搜索适配器上报的 Provider 成本也累加到整树成本。
  • continue_from、停止、失败、续跑和回溯不退还已产生用量。只有批量预留后实际未创建 Trace 的部分会撤销 Agent 预留。
  • 工具内部的模型调用只有在返回 tool_usage 时才能追加记录;remote_* 当前不纳入本地树预算。
  • LLM 次数在调用前预留,Token 和成本在响应后登记。在途响应导致超限时会保留实际消耗,但不再执行该响应的 Tool Call。

用量文件缺失或损坏时 Recursive 会 fail closed。当前原子更新仅由单 Python 进程内每个 root_trace_id 的异步锁保护。

Validator 配置也只在新建 Recursive 根 Trace 时固化:AGENT_VALIDATOR_MODEL 可覆盖普通 Scope 模型,AGENT_ROOT_VALIDATOR_MODEL 可单独覆盖根验收模型。 AGENT_VALIDATOR_SEARCH_PROVIDER=serper 且配置 SERPER_API_KEY 时, Evidence、Hypothesis 和 Root Validator 可使用受控公开网页搜索;默认 disabled,缺少 Provider 时证据不足只能返回 unknown

实现cyber_agent/core/resource_budget.py:ResourceBudgetcyber_agent/core/resource_budget.py:ResourceBudgetControllercyber_agent/trace/store.py:FileSystemTraceStore.replace_resource_usage


兼容性与当前限制

  • legacy 默认启用,并保留一层子 Agent、无每父 6 孩子配额、旧 Goal 自动推进、旧 evaluate 和自然语言 summary。
  • 两种模式共用 Runner、TraceStore 和 ToolRegistry,差异由 AgentPolicy 和 Recursive 协议状态控制,没有复制两套执行引擎。
  • Recursive 目前是单 Python 进程实验版:6 孩子配额、资源用量锁和取消登记都不是跨 Worker 原子机制。
  • 并行模式最多有两个在途模型响应,Token、成本或时间可能在响应返回后出现小幅超限;实际用量仍会记录。
  • 当前没有跨进程 Lease/heartbeat、持久化 cancel request、数据库 TraceStore 原子配额或全树 Scheduler。

关键测试

测试文件 覆盖范围
tests/test_agent_mode.py 模式默认值、配置错误、固化与 Legacy Goal 行为
tests/test_subagent_recursion.py 深度、每父 6 孩子、批量原子拒绝和续跑血缘
tests/test_recursive_tool_capabilities.py 权限交集、内部 context 防伪造和 dispatch 门禁
tests/test_recursive_child_scheduling.py 默认串行、最多 2 并行和 Legacy 隔离
tests/test_recursive_subtree_cancellation.py 子树停止、排队取消和 API Runner 路由
tests/test_recursive_resource_budget.py 预算解析、原子计数、超限和用量持久化
tests/test_recursive_replan_context.py 上下文继承、任务匹配和逐级回退
tests/test_recursive_validation_core.py 分层 Policy、Plan、逐项结果和聚合
tests/test_recursive_validator_web.py 搜索白名单、SSRF、DNS 固定、重定向和限额
tests/test_recursive_validation_artifacts.py ArtifactRef、Resolver、hash 和跨树越权
tests/test_recursive_runtime_extensions.py 根门禁、预算包装和停止后协议行为
tests/test_recursive_context_policy.py 根锚点、TaskBrief 版本、引用授权与限额
tests/test_recursive_context_integration.py 五层上下文、分层 Scope、受控搜索、权限与逐层审核
tests/test_recursive_validator_lifecycle_complex.py 最深层修订和根结果独立验收的五层复杂用例

相关文档

文档 内容
Recursive 任务协议 TaskBrief、TaskReport、ValidationResult、TaskReview 和审核状态机
架构设计 AgentRunner、Trace、Goal 和工具系统全景
工具系统 agent、协议工具与 ToolRegistry 接口
Trace API Trace 存储、续跑、回溯与停止 API
Context 管理 消息 Context 和 Recursive 继承、裁剪规则