RunRequest、Planner 如何为每次任务尝试生成 ExecutionPlan,以及这些类型如何约束组件边界。执行顺序与持久化格式分别由执行、调度与清理和结果与复用说明。
公开导出集中在 src/agentcompass/runtime/__init__.py,具体数据类位于 src/agentcompass/runtime/models/,组件接口位于 src/agentcompass/runtime/base.py。配置和规划的主要实现文件如下:
请求与配置解析
RunRequest 是单次运行的完整输入,包含八个配置段:
ModelSpec 是值对象,不是注册型组件。系统没有 MODELS 注册表;注册表解析 Benchmark、Harness、Environment、Recipe 和分析器,选中的 Harness 或无 Harness Benchmark 直接使用 req.model。向 ModelSpec 增加字段时,应检查请求构造、脱敏、持久化签名以及使用该字段的 Harness,不要为普通端点配置增加注册表条目。
不要混淆 RunRuntimeSpec 和 ResolvedRuntimeOptions。前者属于单个请求,目前负责复用设置;后者位于 runtime 的 models/orchestration.py 模块,负责结果路径、截止时间、清理宽限期、provider 限制、Environment 打开速率、进度与日志等进程级共享行为。
load_run_config 按以下顺序读取实际存在的配置文件:
deep_merge 递归合并映射且不修改任一输入。后出现的标量或列表替换先前值,嵌套映射按键合并。完整字段形式的 ${VAR} 会从环境变量解析;将 ${VAR} 嵌入更长字符串会被拒绝。运行配置中的组件配置段是 benchmarks、harnesses 和 environments,每个选中组件的参数直接平铺在其 ID 下。models 配置段会被拒绝,因为 Model 通过 ModelSpec 提供。
build_run_request、run_evaluation 与 run CLI 等单次运行入口按以下优先级解析,箭头从低优先级指向高优先级:
如果调用方把已构建的
RunRequest 传给 run_evaluation_request,_merge_request_with_config 会用请求中的组件参数覆盖配置中对应的选中组件条目,同时保留请求中的 Model、执行设置、输出设置和显式复用值。已加载的配置路径与解析后的 Recipe 目录写入 RunMetadata。
编排路径由 resolve_orchestration 从 OrchestrationSpec 解析每个命名请求:
全局
task_concurrency 单独按“显式解析器参数 → 编排值 → 运行配置中的执行值 → ExecutionSpec 默认值”解析。Orchestration 的 from_requests() 类方法会把解析结果写入每个请求的 ExecutionSpec,使单请求与多请求路径保持一致。解析阶段还会拒绝未知编排字段,并校验 Benchmark、Harness 和 Environment ID。
Orchestration 包含有序的 OrchestratedRun;每个对象都保存稳定的编排键、声明序号、请求名称和完整的 RunRequest。单个请求的终态使用 RequestOutcome 表示,OrchestrationResult 按声明顺序保留所有请求结果。
任务与计划契约
Benchmark 按以下流程将数据集内容转换为 runtime 输入:PreparedTask.input 是 TaskInput,包含提示词,以及可选的系统提示词、媒体、文件、工作区、工具和消息;PreparedTask.output 是 TaskOutput,包含预期答案与输出文件声明。数据集原始记录应保留在 TaskSpec.metadata,只有可执行材料才应放入 PreparedTask。
ExecutionPlan 表示一次任务尝试的已解析计划,并非整个任务共用的固定计划。执行时,UnifiedEvaluationRuntime 的 _run_attempts 方法会在语义尝试循环内、runtime 重试循环外调用 Planner.plan。因此,每次语义尝试都会重新构建计划,受 max_retries 限制的 runtime 重试则复用该次尝试的计划;Recipe 不能依赖上一次规划产生的副作用。具体源码位置与上下游调用链见源码地图。
每次规划依次执行以下步骤:
- 解析评测 Environment 模式。
- 解析基线、运行与评测阶段的网络策略输入。
- 深拷贝请求的
EnvironmentSpec,得到任务局部配置。 - 调用
benchmark.build_plan创建 Benchmark 子计划。 - 调用
harness.build_plan;无 Harness Benchmark 则创建基础HarnessPlan。 - 按注册表顺序应用每个允许且匹配的 Recipe。
- 使用默认模式为
public的NetworkPolicy()补齐缺失策略。 - 根据最终评测模式创建或清除
evaluation_environment。
TaskSpec 提示。匹配的 Recipe 随后可以转换该值,仍缺失时才补为 public。Recipe 必须保留兼容的用户显式设置。规划结束后,runtime 会调用 _resolve_execution_plan_network_policies,让选中的 provider 解析并校验其实际强制执行的策略;Environment 打开前只持久化脱敏后的审计视图。
编排试运行会解析配置、校验组件兼容性并打印完整请求,但不会加载任务或执行 Planner.plan。要检查逐任务计划,可读取 run_info.json 的 resolved_execution_plans:先按 task_id 定位任务,再进入 attempts 并选择尝试编号;也可以订阅 execution_plan_resolved 进度事件。持久化视图只保留 Environment ID、阶段策略、评测模式和已应用的 Recipe ID。如需增加调试信息,应向 _resolved_execution_plan_payload 增加安全字段,不能直接保存完整数据类。
Recipe 规划
内置 Recipe 通过src/agentcompass/runtime/registry.py 中的 RECIPES 注册。src/agentcompass/runtime/recipes.py 中的 build_run_recipe_registry 将这些条目复制到本次运行的注册表,再追加从受信任的 RunMetadata.recipe_dirs 目录中加载并校验的 Recipe 类。
ExecutionSpec.enabled_recipes 控制候选集合:
- 空列表表示考虑本次运行注册表中的全部 Recipe,再由
matches选择适用项; - 非空列表是 Recipe ID 白名单;
- 每个匹配的 Recipe 接收上一个 Recipe 返回的计划,其 ID 会追加到
ExecutionPlan.applied_recipes。
BaseRecipe 提供两个方法:
matches 与 apply 在规划期间运行,不能打开 Environment、安装软件、调用 Model、修改任务文件或评测答案。apply 应返回复制后的计划,并保留兼容的用户显式值。可参考 src/agentcompass/recipes/swebench_verified/ 下 common.py 中的 clone_execution_plan。
Recipe 只负责读取 TaskSpec 或 Benchmark 子计划中的稳定要求,调整计划里的 Environment 参数和 Benchmark/Harness 执行细节。Environment provider 负责 sandbox 创建与策略强制执行,Benchmark 负责评分。
Environment 会话契约
BaseEnvironment.open 返回 EnvironmentSession。该会话提供异步命令执行、上传与下载、文本 I/O、目录传输、端点发现、文件检查和可选的动态网络切换;具体方法签名见 src/agentcompass/runtime/base.py 中的 EnvironmentSession。
命令参数的约束是明确的:exec(..., shell=False) 接受 list[str],exec(..., shell=True) 接受字符串。各 provider 应保持 ExecResult.returncode、stdout、stderr 和 timed_out 的统一语义。Environment 的打开、复用和清理顺序见执行、调度与清理。
兼容性与结果类型边界
RunResult 表示一次执行或评测尝试,不是请求级汇总。Harness 负责记录状态、答案、轨迹、产物与执行错误;Benchmark 的 evaluate 负责 correct、score 和评测错误,aggregate_metrics 负责请求级指标并返回经过校验的 MetricResult。runtime 再把尝试整理为任务明细和请求摘要,Orchestrator 则用 RequestOutcome 与 OrchestrationResult 表示命名请求及整组编排的终态。
TaskStatus.COMPLETED、RUN_ERROR、EVAL_ERROR 和 SKIPPED 含义不同。TaskStatus.ERROR 序列化为 run_error_or_eval_error,表示无法进一步确定阶段的错误。规范化时不能把有效的 score=0 当作错误,也不能丢失错误阶段。各层的持久化结构见结果与复用。
修改共享契约时,应检查以下边界:
- runtime 数据类的构造、校验和公开导出;
- CLI、SDK 与编排解析生成请求和结果对象的位置;
- Benchmark、Harness、Environment、Recipe 和分析器对共享对象的生成与使用;
RunRequest.to_task_payload、to_persistence_params、明细整理、脱敏和复用加载;- 对已有结果目录进行分析与重新汇总时的反序列化。
