为每个阶段选择策略
网络策略会针对每个任务独立解析。Benchmark loader 可以在每个TaskSpec 上声明网络策略字段,因此同一次运行中的两个 sample 可以使用不同策略。通过 --env-params 传入的值作用于整次运行,会显式覆盖每个已选 sample 的对应阶段:
这不是四个依次执行的阶段。shared 评测是一个环境 baseline 加 run/evaluation 两个阶段覆盖;fresh 评测有两个环境,各有一个 baseline,但执行阶段仍只有 run 和 evaluation。Harbor 将
[environment].network_mode 映射到 agent 基线,将 [verifier.environment].network_mode 映射到独立 verifier 基线;[agent].network_mode 与 [verifier].network_mode 仍是阶段覆盖。请求中的 evaluation_baseline_network_policy 只适用于 fresh,优先于公共请求 baseline,再回退到任务的 verifier 基线或继承的 agent 基线。显式空的 Harbor verifier 环境使用独立的默认 public 基线。
每个阶段按以下优先级解析:
省略字段表示“继续使用下一层来源”;如果没有来源提供该阶段,就独立取
public。因此在没有其他来源提供策略时,显式传入 public 与不传值的实际策略相同。需要强制整次运行使用同一策略时使用 --env-params;需要保留官方逐 sample 行为时则省略这些覆盖,让 Benchmark 加载任务策略。Recipe 可以检查 Harness 所需的 endpoint,但不会改变已经解析出的策略;最终策略和 applied_recipes 会记录这一结果。
Harness 准备在应用
run_network_policy 之前发生,因此可信 Harness 可以在基线策略下安装 runtime,再在更严格的策略下运行不可信 agent。网络阶段是函数级信任边界,并非为每个进度阶段分别设置一项策略。理解函数级边界
AgentCompass 对两种评测 Environment 模式应用同一条 evaluation 规则:只有完整的benchmark.evaluate() 函数调用使用 evaluation_network_policy。两种模式的区别在于 fresh 会创建另一个 Environment,而 reuse 在 agent Environment 中执行评测。fresh 运行中的 evaluate_environment 只是进度阶段,不是独立的 Benchmark hook;其准备边界对应评测 provider 的 open() 调用。
下表展示 Environment 操作执行时的有效策略。AgentCompass host 发出的 provider control-plane 请求位于 sandbox 网络强制范围之外。一个函数内部可以包含多个操作;runtime 不会继续把这些操作拆分成更细的策略作用域。
Shared Environment
reuse 时,始终使用同一个 Environment,其生命周期函数依次经过 baseline、run 和 evaluation 策略:
在第 7 步之前,runtime 会从
run_network_policy 直接切换到 evaluation_network_policy,调用完整的 benchmark.evaluate() 函数,并在 finally 中恢复 baseline_network_policy。这样无需经过一次中间 baseline 切换,也能把 evaluation 策略限制在评测函数范围内。
Separate Environment
fresh 会先结束 agent Environment 的生命周期,再创建独立的 evaluation Environment:
第 8 步是选择
fresh 后引入的条件性评测 Environment 准备阶段,并不是可选的 Benchmark hook。runtime 只在 evaluation_provider.open() 完成后切换到 evaluation 策略,在 benchmark.evaluate() 结束后立即恢复评测 Environment 的基线策略,然后释放或保留该 Environment。
runtime 直接执行声明的收集命令,没有命令就跳过准备,并在保存开启时收集已有文件。命令执行和产物下载都处于 run 信任边界内,不会产生新的网络阶段。
网络模式
每个阶段支持四种 mode:public 和 no-network 可直接使用字符串:
api.*.example.com 这类嵌入式 wildcard。Allowlist 和 denylist 均接受 www.example.com 这样的裸 host、www.example.com:443 这样的 host:port 简写,以及 {"host": "www.example.com", "port": 443} 这样的 target object。裸 host 表示该 host 的所有端口;port 必须是 1..65535 的整数。IPv6 指定端口时使用 [2001:db8::1]:443。无法精确执行端口限制的 Provider 会拒绝带端口 target。
告知 agent 运行阶段的网络限制
默认情况下,当实际生效的run_network_policy 为 no-network、allowlist 或 denylist 时,每个 Harness 会在最终用户指令末尾追加一段英文网络限制声明。这样可以避免 agent 将有意施加的限制误判为临时网络故障并反复重试被阻止的操作。public 策略不会追加声明。
声明基于 provider 解析后的实际策略,而不只是请求值。因此 Recipe 添加的 target 会出现在 allowlist 声明中,allowlist 和 denylist 中的 target 会使用实际策略中的完整值替换。Provider 无法执行请求的策略时会在 rollout 前拒绝运行,而不是注入误导性的声明。
no-network 使用相同的 wrapper,但不包含 target 列表:
denylist 会使用实际禁止的 target 替换列表:
benchmark.evaluate() 仍接收原始输入。标准 Harness 路径支持普通 prompt、结构化 user message、多模态 user message,以及 openai_chat 接受的 JSON 编码 message。harness-free TauBench 推理路径目前不会消费该声明。
通过所选 Harness 的配置关闭注入:
harnesses.<id> 下设置 inject_network_restriction_notice: false;Python 调用方则把同一字段放入 harness_params。该设置只改变 Harness 输入声明,不会改变或关闭网络策略的强制执行。
从 CLI 传入阶段策略
通过--env-params 中的 JSON 字段传入三种 runtime 策略:
也可以通过 Python API 的
environment_params 传入相同字段,或者由 Benchmark loader 在 TaskSpec 上声明 sample 级策略。
选择最小可用策略
按以下顺序决定:- 查看 Benchmark 页面声明的官方或推荐策略。
- 确认 Harness 在哪里安装,以及 model API 请求从哪里发出。
- sandbox 需要安装软件包或可执行文件时保持基线策略为
public;否则优先允许列表或预构建镜像。 - 任务应只使用本地证据时,将运行阶段设为
no-network。 - Harness 关闭或 artifact 收集所需的 endpoint 必须包含在运行策略中;rollout 与验证之间不会放宽策略。
- 只添加依赖网络阶段真正需要的 model、搜索、评委、软件包或 artifact host。
- 先运行一个任务并检查解析后执行计划,再扩大规模。
harness.start_session 在 Environment 内安装的软件包或 CLI 工具使用基线策略。若基线策略也必须是 no-network,需要先把依赖放入任务镜像或快照。
model 端点是否需要允许列表,取决于 Harness 在哪里发出请求:
- 本地 Harness 进程从 AgentCompass 主机调用 model,不受任务 Environment 策略控制。
- 在 sandbox 内运行的 Harness 需要把 model 端点加入运行阶段允许列表。
- 部分 Benchmark Recipe(包括 DeepSWE)会推断实际 model 端点。不要假设所有自定义 Benchmark 或外部 Recipe 都会这样做;请检查解析后计划。
run_network_policy的语义与来源无关。DeepSWE 会校验所需 model 端点是否被允许;如果 task 或 CLI 的有效策略阻止这些端点,计划构建会失败,Recipe 不会扩大该策略。remote Harness 需要使用 CLI 显式覆盖为包含模型 host 的allowlist;local Harness 可以继续使用no-network。
provider 支持
Daytona 最多接受 20 个域名条目或 10 个 IPv4 网络条目。Docker 的
network 设置为 none、host 或 container:<id> 时不能使用动态阶段策略。默认 egress proxy 镜像是 python:3.12-alpine;离线主机需要确保 Docker 守护进程已能获取该镜像。
出站策略只接受上面的通用字段。Provider 原生 block-all 和允许列表参数会报错;适配器从最终通用策略生成对应 API 选项。
Docker 是当前公开文档中唯一能够强制执行
denylist 的 Provider。其他公开 Provider 会拒绝该策略,而不会静默放宽为 public。验证实际 Policy
使用持久化调试日志运行一个已知任务:baseline_network_mode、run_network_mode 和 evaluation_network_mode。每个任务详情还会保存最终策略与 applied_recipes。由于 Benchmark Recipe 可能添加推断端点或 provider 适配,请验证实际解析后的值,不要只依赖原始命令。
进行对抗性隔离测试时,可以要求 agent 访问一个已知外部 URL,并同时确认:
- 受限运行阶段中请求失败;
- 同一个 Environment 仍能完成基线策略允许的可信准备工作。
NetworkOperationAnalyzer 可以汇总 curl、wget、软件包安装或 git clone 等命令。它只能观察 agent 行为,不会强制策略,也不能替代 provider 切换日志。
