Skip to main content
当 Benchmark 需要根据 Environment 为每个任务确定性地调整 ExecutionPlan 时,新增一个 Recipe。 Recipe 属于规划策略。它可以选择镜像、工作区、资源、网络设置或专用的 Benchmark/Harness 计划,但不能打开 sandbox、安装软件包、调用 Model 或 provider、执行任务或进行评分。应把这些副作用放在负责相应生命周期的组件中。

选择集成方式

外部 Recipe 代码在 AgentCompass 进程中执行,不受任务 sandbox 隔离。只能加载经过审查且可信的软件包。

实现基础契约

每个 Recipe 都必须继承 BaseRecipe、支持无参数构造、具有唯一 id,并实现 matches()apply()
matches(req, task, plan) 只能判断 Recipe 是否适用。它接收的当前执行计划已经包含此前匹配 Recipe 所做的变更;该方法不能修改任何参数。 apply(plan, req, task) 必须返回新的 ExecutionPlan。修改嵌套的 Environment、Benchmark 或 Harness 计划字段前,应深拷贝传入的执行计划。必须保留兼容的用户显式值,通过 setdefault() 或等价的后备逻辑补齐缺失字段。显式值不兼容时,应报错并说明解决办法,不能静默替换。 这两个方法都属于确定性规划。不能在其中访问网络、写入文件、启动子进程、安装软件包、创建 sandbox、调用 Model 或产生其他外部可见副作用。

注册内置 Recipe

将公开实现放在 src/agentcompass/recipes/ 下,然后注册:
在各级 __init__.py 中导入该模块,确保导入 agentcompass.recipes 时会执行装饰器。注册表以 id 为键并拒绝重复 ID。provider 专属适配应放在 Recipe 中,不能把 Environment 机制移入 Benchmark。 内置 Recipe 只能面向公开 provider 和公开基础设施。组织专属部署策略应放在可信外部软件包中。

打包可信外部 Recipe

外部 Recipe 目录必须是 Python 软件包,不能只是单个 Python 文件:
定义类时不要使用进程级 RECIPES 注册表装饰它:
再从软件包根模块导出同一个类:
加载器要求同时满足以下条件:
  • 目录存在且包含 __init__.py
  • RECIPE_CLASSES 是非空列表或元组;
  • 每一项都是具体的 BaseRecipe 子类,并具有非空且唯一的 id
  • 每个类都支持无参数构造。
相对目录从当前工作目录解析。AgentCompass 会规范化路径并去重,先复制内置注册表作为本次运行的注册表,再追加外部类。如果 ID 重复,注册阶段就会报错,与内置 Recipe 冲突也不例外。 完成 Benchmark 示例和 Harness 实现教程中的 example_exact_matchexample_answer 后,运行对应的确定性任务,同时加载该 Recipe 并将其加入允许列表:
--recipe 是允许列表,不是强制执行开关;Recipe 仍需让 matches() 返回 True。CLI、SDK、配置文件和编排的对应方式见 Recipe

理解应用顺序

当前规划器会为每次任务尝试构建默认执行计划,然后按插入顺序遍历本次运行的 Recipe 注册表:
  1. 如果 execution.enabled_recipes 非空,跳过注册 ID 不在允许列表中的条目。
  2. 无参数构造 Recipe。
  3. 使用当前已生成的执行计划调用 matches()
  4. 匹配时,将当前执行计划替换为 apply() 的返回值,并在 applied_recipes 中记录 Recipe id
  5. 继续处理下一个注册项;它可以检查更新后的执行计划。
内置 Recipe 保持注册时的插入顺序。外部类追加在内置项之后,先按 runtime.recipe_dirs 的顺序,再按各软件包中 RECIPE_CLASSES 的顺序处理。所有匹配 Recipe 都会应用;规划器不会自动解决重叠写入。 BaseRecipe 当前声明了 priorityenabled_by_default,但规划器不会读取这两个属性。不能声称 priority 会改变顺序,也不能把其中任一属性当作启用机制。Recipe 是否参与由注册状态、execution.enabled_recipesmatches() 共同决定。 注册顺序是当前执行语义,但不能代替清晰的职责边界。应避免多个 Recipe 写入相同字段,也不要让正确性依赖无关模块的导入顺序。

验证集成

首先确认软件包能加载且 ID 存在。当前没有 agentcompass list recipe 命令,因此外部软件包需要直接检查本次运行的注册表:
然后使用 --task-concurrency 1--max-retries 0DEBUG 日志运行一个已知任务,并验证:
  • 对无关 Benchmark 或 Environment,matches() 返回 False
  • run_info.jsonresolved_execution_plans 中,相应任务尝试的记录包含预期 ID;终端输出顶层的 applied_recipes 列表也包含该 ID;
  • 每次保存的任务尝试都对应一份包含预期值的解析后执行计划;
  • Recipe 应用后,兼容的显式镜像、工作区、资源或网络值保持不变;
  • 所选 Environment 能根据调整后的执行计划构建配置,并在成功和失败后都完成清理。
如果两个 Recipe 可能同时匹配,应验证两种组合,或重新划分职责以消除重叠。PR 所需的代码仓库检查和单任务证据见测试与验证

完成检查表

  • 该行为属于确定性的逐任务规划,而不属于 Benchmark、Harness、Environment 或 runtime 机制。
  • matches()apply() 的结果确定,且不会产生副作用。
  • apply() 返回复制后的执行计划,并保留用户显式意图。
  • Recipe ID 唯一,并能通过正确的内置注册路径或 RECIPE_CLASSES 加载。
  • 已验证匹配、不匹配、显式覆盖、解析后的执行计划和清理行为。
  • 已用中英文记录面向用户的行为和支持组合。