Evaluation as Exit Codes

Evaluation as Exit Codes 用来补上物理执行不会自动给出的结果信号。配置过的 物理 Tool 完成后,Harness 会通过隐藏的执行后 hook 调用独立评估器。

评估器只接收:

  1. 被选中 Tool 的后置条件;

  2. 与该 Tool 的 run_id 关联的执行后 Observation。

它不会接收执行模型的 reasoning、自我报告、当前用户指令或后端结果字段。

公开版本提供什么

Thea 提供

部署方提供

隐藏 evaluate_run Tool 和结构化执行后触发逻辑

每个被评估物理 Tool 返回非空 run_id

EvaluatorProtocol 和类型化三态判定

自定义评估器或配置给 ModelEvaluator 的模型

PostExecutionObservationProvider

从 run_id 解析客观执行后证据

每个 Tool 的后置条件边界

每个物理 Tool 的真实成功标准

对 process、success、failure 的校验

分段执行策略的语义

success-gated Scene Graph update

部署侧由执行结果推导出的图状态变化

公开包不包含机器人产物目录、策略日志格式、相机同步逻辑或通用 后置条件。

判定结果协议

from harness import EvaluatorVerdict

verdict = EvaluatorVerdict(
    status="failure",
    evidence=(
        "the bottle remains on the table",
        "the gripper closed without lifting it",
    ),
    failure_reason="the robot stopped too far from the bottle to grasp it",
)

status 只能是:

  • process:执行应继续进入另一个动作片段;

  • success:后置条件已满足;

  • failure:执行应停止,失败原因返回 Agentic Loop。

只有列在 evaluation.segment_tools 中的 Tool 才能返回 process。

绑定后置条件

进程内 Tool 可以直接携带判定标准:

from harness import BuiltinTool

registry.register(
    BuiltinTool(
        name="pick_object",
        description="Pick one confirmed Scene Graph ref.",
        input_schema={
            "type": "object",
            "properties": {"target": {"type": "string"}},
            "required": ["target"],
            "additionalProperties": False,
        },
        fn=pick_object,
        post_condition=(
            "The requested object is visibly lifted and held by the gripper."
        ),
    )
)

MCP Tool 可以在配置中按名称映射同样的协议:

evaluation:
  required_tools: [pick_object]
  segment_tools: []
  max_segments: 8
  post_conditions:
    pick_object: >-
      The requested object is visibly lifted and held by the gripper.

每个被评估 Tool 都必须返回非空 run_id,即使后端自己报告失败。后端状态不是 物理判定结果。

连接执行后证据

部署方决定 run_id 如何解析为证据:

from harness import Observation


class MyPostExecutionObservationProvider:
    def capture(self, run_id: str) -> Observation:
        return capture_observation_for_run(run_id)

返回的 Observation 不应包含本地路径,也不应绑定某个后端实现。它可以携带命名 相机视图、base clearance、timestamp、来源信息和紧凑摘要。ModelEvaluator 默认最多转发三个命名视觉视图。

选择评估器

可以使用内置的模型评估器:

from harness import ModelEvaluator
from harness.models import build_model

evaluator = ModelEvaluator(
    build_model(
        "openai",
        model="gpt-4o-mini",
    )
)

也可以实现确定性、学习型或服务后端支撑的评估器:

from harness import EvaluationRequest, EvaluatorVerdict


class MyEvaluator:
    def evaluate(self, request: EvaluationRequest) -> EvaluatorVerdict:
        return judge_post_condition(
            request.post_condition,
            request.post_execution_observation,
        )

实现必须返回 EvaluatorVerdict。

组合 Harness

harness = Harness(
    config,
    registry=registry,
    evaluator=evaluator,
    post_execution_observation_provider=(MyPostExecutionObservationProvider()),
    scene_graph=scene_graph,
)

调用链如下:

evaluated physical Tool
  -> automatic post-execution hook
  -> hidden evaluate_run(run_id, target_tool_name)
  -> PostExecutionObservationProvider.capture(run_id)
  -> EvaluatorProtocol.evaluate(post-condition, Observation)
  -> process | success | failure

模型不能选择 evaluate_run。Harness 从完成的物理 Tool 派生该调用,并且不会把 它的 Tool Definition 暴露给模型。

复现完整行为

在另一台机器人或策略上复现时:

  1. 为每个被评估 Tool 定义可见、可测试的后置条件。

  2. 让 Tool 在物理执行开始后返回稳定 run_id。

  3. 保留判断该 run 所需的证据。

  4. 实现 capture(run_id),返回类型化的执行后 Observation。

  5. 配置 ModelEvaluator 或实现 EvaluatorProtocol。

  6. 将 Tool 加入 evaluation.required_tools。

  7. 如果 Tool 分段执行,将其加入 evaluation.segment_tools 并设置 max_segments。

  8. 验证只有 success 才能触发 Scene Graph 执行更新。