跳到主要内容

第 19 章:使用 Harbor 内置 Agent

同一个故障诊断 Task,oracle 能通过,换成 claude-code 后却在模型请求之前失败。团队随即更换模型,错误仍然存在。最后发现,容器没有安装 Agent CLI 所需的系统包,而且 Task 的网络基线禁止了安装阶段访问软件源。模型从未看到指令,所谓“模型失败”其实是 Agent setup 失败。

内置 Agent 的价值,在于 Harbor 已经替你实现了一批安装、Headless 调用、认证注入和轨迹转换适配器;它并不表示任意 Agent 都能搭配任意模型、操作系统、MCP Server 或 Skill。更不能仅凭 --agent 名称,就把两个运行视为公平对照。本章把 Agent 作为一个需要版本化、预检和审计的实验组件。

完成本章后,你应该能够:

  • 解释 BaseAgentBaseInstalledAgent、Factory 与 Trial 生命周期的分工;
  • 从 Harbor v0.18.0 源码生成准确的内置 Agent 清单;
  • 在调用模型前检查安装、认证、模型命名、Headless、操作系统和轨迹能力;
  • 固定 Prompt、轮次、超时和工具权限,运行一个可复核的内置 Agent Job;
  • 区分配置、安装、认证、Agent 执行和 Verifier 失败,并据此设计公平比较。

19.1 名称背后是一段执行协议

AgentConfig 最终不会直接执行字符串。Trial 先把配置交给 AgentFactory:Factory 解析宿主机环境变量模板,按注册名或 import path 导入类,再把 model_namekwargs、MCP 和 Skill 等参数传入实例。BaseAgent 只规定四个关键动作:报告名称、报告版本、setup()run()run() 还接收 AgentContext,供实现回填 token、成本和 trajectory 等结果。12

Harbor 文档把集成分为两类:一种通过 BaseEnvironment 操作沙箱,另一种继承 BaseInstalledAgent,把第三方 Agent 安装到任务环境并以 Headless 模式运行。3 本章把后者称为 Installed Agent。不要把“非 Installed”机械理解成“运行在宿主机”:terminus-2computer-1 等内置执行器仍通过 Harbor 的环境接口工作,只是没有走 BaseInstalledAgent.install() 这一套公共骨架。

Installed Agent 的基本生命周期如下:

解析 Job/Task

├─ 创建 Agent 与 Environment
├─ 启动环境、健康检查、上传 Skill
├─ Agent setup:安装 CLI、检测版本
├─ Agent run:渲染 Prompt、注入认证、Headless 执行
├─ 同步 Agent 日志与 trajectory
└─ Verifier:独立判断最终状态

BaseInstalledAgent.setup() 先调用具体实现的 install(),只有未显式指定版本时才尽力执行版本探测;探测异常会被忽略。因此,“结果里出现某个版本”与“安装时真正锁定了该版本”不是同一件事。正式实验应在 kwargs.version 中固定第三方 CLI 版本,并在预检后核对 agent_info.version4

这里还有一个常被忽略的网络边界。Agent Environment 用 Task 的 [environment] 网络策略作为启动基线;只有进入 agent.run() 时,Harbor 才会按 Agent phase 策略临时切换网络。extra_allowed_hosts 的模型字段也明确限定为 agent.run()。由此可以推断:在线安装发生在 setup 阶段,它使用环境基线,而不是 --allow-agent-host 增补后的 Agent phase 策略。一个基线为 none 的 Task 即使允许模型 API 域名,也可能无法下载 Agent CLI。解决办法是把 Agent 预装进镜像,或为 setup 保留必要网络;不要把软件源域名误加到只作用于 run() 的参数上。5

19.2 v0.18.0 的内置 Agent 清单

本书不从网页宣传语复制清单,而是读取固定提交中 AgentFactory._AGENT_MAP。该映射在 v0.18.0 恰好包含 32 个名称。下面按基类和 ATIF(Agent Trajectory Interchange Format)能力分组;组内每个名称都是可传给 Factory 的精确字符串。6

组别数量精确名称
非 Installed、支持 ATIF2terminus-2computer-1
非 Installed、不声明 ATIF3oraclenopdspy-rlm
Installed、支持 ATIF24acpclaude-codecopilot-clicline-clicodexcursor-cligemini-cliantigravity-clirovodev-cligoosehermeskimi-climini-swe-agentnemo-agentswe-agentopencodemimoopenclawopenhandsopenhands-sdkqwen-coderdevintrae-agenteve
Installed、不声明 ATIF3aiderlanggraphpi

acp 是通用运行器;acp:<id>@<version> 是运行时解析的 Registry 简写,不是额外的固定内置类。省略 ACP 版本会在 setup 阶段访问 Registry 的分支来解析最新条目,这不适合要求离线复现的实验。7

注意:v0.18.0 的 AgentName 枚举还包含 terminusterminus-1,CLI 帮助的 metavar 也从整个枚举生成;但 Factory 映射没有这两个名称。传入后会在创建阶段得到 unknown agent 错误。这个版本里应以 Factory 映射为可创建清单,而不是只看帮助中的候选词。8

ATIF 标志也只回答“该适配器声明能够产出 Harbor 标准轨迹”,不保证每次运行一定留下有效轨迹。CLI 崩溃、日志同步失败或转换器遇到未知事件格式,都可能让 trajectory 缺失。反过来,SUPPORTS_ATIF=False 不意味着 Agent 无日志,只表示不能把其私有日志当成标准 ATIF 使用。

操作系统边界更严格:v0.18.0 的预检只允许 oraclenop 运行 Windows Task,其余 Factory 内置 Agent 均为 SUPPORTS_WINDOWS=False,并在 setup 前拒绝。9

可以在固定源码树中运行下面的无网络探针,重新生成清单和能力位:

cd /private/tmp/harbor-framework-v0.18.0
uv run --frozen python - <<'PY'
from harbor.agents.factory import AgentFactory
from harbor.agents.installed.base import BaseInstalledAgent

rows = []
for name in AgentFactory._AGENT_MAP:
cls = AgentFactory.get_agent_class(name)
rows.append((
name.value,
issubclass(cls, BaseInstalledAgent),
cls.SUPPORTS_ATIF,
cls.SUPPORTS_WINDOWS,
))

assert len(rows) == 32
assert {r[0] for r in rows} == {n.value for n in AgentFactory._AGENT_MAP}
for row in rows:
print(*row, sep="\t")
PY

这个探针只导入和检查类,不安装第三方二进制,也不调用模型。它适合放进版本升级检查:当映射、能力位或导入依赖变化时,先审查差异,再更新兼容矩阵。

19.3 先做兼容性预检

内置只表示“Harbor 有适配器”。在决定运行前,至少回答以下问题:

  1. Factory 能否创建该名称,还是只有枚举或文档提到它?
  2. Task 是 Linux 还是 Windows;Agent 是否声明支持?
  3. Agent setup 需要什么包管理器、网络和容器用户?二进制能否固定版本?
  4. wrapper 接受怎样的 model_name,会不会删除 Provider 前缀?
  5. 认证从 API Key、OAuth 文件还是云凭据链取得?
  6. Headless 命令如何处理确认提示和标准输入?
  7. 工具、MCP、Skill 和网络能力是否真的由该实现支持?
  8. 是否产出 ATIF;失败后还能取得哪些原生日志?

下表只比较本章查过源码的三个代表性 CLI Agent,不应外推到其他 29 个名称:

项目claude-codecodexgemini-cli
模型处理显式模型推荐写 provider/model;官方 Anthropic 路径会去掉第一个前缀,自定义 Base URL 保留全名必须非空;运行时取最后一个 / 后的部分必须含 /;运行时同样取最后一段
常用认证ANTHROPIC_API_KEY;也有显式强制 OAuth 与 Bedrock 分支默认 OPENAI_API_KEY;可显式选择 auth.jsonGemini API Key、Vertex 环境变量或显式 OAuth 凭据文件
Headless 入口claude --print --output-format=stream-jsoncodex exec --jsongemini --prompt ...
默认自动化权限wrapper 的 permission_mode 默认 bypassPermissionswrapper 固定传入跳过确认与内部沙箱参数wrapper 固定传入 --yolo
ATIF

这些差异解释了为什么“同一个模型名”仍可能不兼容。比如 Codex 和 Gemini wrapper 都只把最后一段传给 CLI;带多层路径的模型标识可能失去中间部分。Claude Code 还根据官方 API、自定义 Base URL 或 Bedrock 选择不同的模型传递规则。三个 wrapper 的认证优先级和凭据文件注入方式也不同。101112

Harbor 的 Headless 参数与上游 CLI 的非交互能力相呼应:Claude Code 官方参考把 --print 定义为非交互输出,并提供 --max-turns、工具权限和 permission mode;Gemini CLI 官方文档把 --prompt--yolo 列为 Headless 选项。1314 但 Harbor 固定的是自己的 wrapper 行为,而不是上游 CLI 永久不变的接口。第三方版本升级后,必须重跑安装与命令构造测试。

警告bypassPermissions、Codex 的 dangerous bypass 和 Gemini 的 --yolo 都是高自治设置。它们消除 Headless 卡在人工确认处的问题,却不能代替容器用户、网络策略、资源限制和独立 Verifier。尤其不要挂载 Docker socket、云平台管理凭据或宿主机目录后,再把“运行在容器里”当成完整隔离。

19.3.1 认证文件不是普通配置文件

API Key 路径最简单:在 AgentConfig.env 中使用 ${HOST_VAR} 模板,让 Factory 在创建 Agent 时解析,再由 Trial 只在 setup/run 的命令作用域内合并。不要把模型凭据放进 Task 的 [environment.env]:后者属于任务环境本身,会扩大能读到凭据的进程范围,也会混淆“任务输入”和“Agent 认证”两种不同职责。

文件型认证更需要逐实现核对。Codex wrapper 默认使用 OPENAI_API_KEY,只有显式设置 CODEX_AUTH_JSON_PATHCODEX_FORCE_AUTH_JSON 才上传 auth.json;Gemini wrapper 的 OAuth 也必须通过路径或 force 变量显式启用,上传后会调整属主、复制为 0600,结束时再尽力删除。Claude Code 在 API Key 与 OAuth token 同时存在时默认优先 Key,除非显式强制 OAuth。111210

“尽力删除”不能证明密钥从镜像层、Provider 快照、进程环境、崩溃转储和下载日志中彻底消失。高保证场景应使用短期凭据、最小权限账户、一次性沙箱和运行后吊销,并验证所选 Environment Provider 的快照与日志策略。订阅凭据能否用于自动评测还受相应服务条款约束;Harbor 的技术适配不等同于授权。

安装链也是供应链边界。以 Claude Code 为例,wrapper 能固定目标版本,但在非 Alpine 路径会下载并执行上游 bootstrap 脚本。版本 pin 可以阻止无意升级,却不等于对安装脚本和所有传递产物做内容哈希验证。对可审计的基准,应在受控构建流程中预装 Agent,锁定基础镜像 digest 和包完整性,正式 Trial 只验证 --version,不临时执行远程安装脚本。15

19.4 Prompt、轮次和超时是三组不同控制器

Installed Agent 可以通过 prompt_template_path 在宿主侧渲染 Jinja2 模板。模板必须引用 {{ instruction }};渲染使用 StrictUndefined,出现未定义变量会失败,而不是悄悄留空。16 这非常适合把评测协议与 Task 原始 instruction 分离。创建 prompts/incident-agent.j2

你正在封闭的评测环境中处理系统故障。

规则:
- 先收集证据,再修改文件;
- 不猜测服务状态,使用容器内可用命令验证;
- 不访问外部互联网;
- 完成后留下简短的诊断与验证记录。

原始任务如下:

{{ instruction }}

Prompt 模板不是隐藏答案,也不应包含某个 Task 的目标文件内容。公平比较时固定模板字节并记录 SHA-256;如果要比较两个 Prompt,就把 Prompt 明确列为实验变量,不能再把差异归因给 Agent。

轮次是 Agent 自己理解的循环次数。例如 v0.18.0 的 Claude Code wrapper 把 max_turns 映射成 --max-turns,还暴露思考、预算、fallback model、工具和 permission mode 等 Agent 专属参数。kwargs 不是跨 Agent 的统一标准;把 Claude 的 max_turns=12 原样传给另一个实现,可能被忽略,也可能在构造时失败。17

超时则由 Harbor 包围整个阶段:

  • setup 默认上限为 360 秒,可用 override_setup_timeout_sec 或 multiplier 调整;
  • Agent 执行基线来自 Task 的 [agent].timeout_sec,Job 的 override_timeout_sec 可替换它;
  • Job 的 agent_timeout_multiplier 只缩放 Agent 执行,agent_setup_timeout_multiplier 单独缩放安装;
  • max_timeout_sec 是运行配置的封顶值,不是轮数。

如果 Task 没有 Agent timeout,单步 Trial 的 Agent 执行 timeout 可以是 None。生产评测不要只设 max_turns 而省略 Harbor timeout:CLI 可能卡在网络、子进程或未知提示上,未必消耗新的模型轮次。18

工具权限同样有三层:Agent CLI 的工具策略、Task 容器的 OS 权限、Harbor 的网络与 Artifact 边界。Claude Code 的 allowed_tools 表示无需询问即可使用的工具,不应误读成安全白名单;严格禁止项要使用 disallowed_tools,外网仍应由 Harbor 网络策略阻断。即使禁止 WebFetchBash 仍可能调用 curl,所以工具名过滤不能替代 egress 控制。13

19.5 一个可核验的 Claude Code Job

下面把前几章的本地 Dataset 接入内置 claude-code。示例锁定 Harbor v0.18.0,并把第三方 Claude Code CLI 固定为 2.1.204;该包版本在 2026-07-16 已从 npm Registry 核验存在。19 模型标识沿用 v0.18.0 随附教程中的 anthropic/claude-sonnet-4-5。运行前仍应确认你的账户有权访问该模型。20

从书稿配套项目根目录创建 configs/ch19-claude.yaml

job_name: ch19-claude-controlled
jobs_dir: jobs
n_attempts: 1
n_concurrent_trials: 1
timeout_multiplier: 1.0

environment:
type: docker
force_build: false
delete: true

agents:
- name: claude-code
model_name: anthropic/claude-sonnet-4-5
n_concurrent: 1
override_timeout_sec: 900
override_setup_timeout_sec: 600
kwargs:
version: "2.1.204"
prompt_template_path: prompts/incident-agent.j2
max_turns: 12
max_budget_usd: "2.00"
disallowed_tools: WebFetch
permission_mode: bypassPermissions
env:
ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY}"

datasets:
- path: datasets/system-config-benchmark
task_names:
- diagnose-python-service

YAML 中没有真实 Key。Factory 创建 Agent 时才把完整匹配的 ${ANTHROPIC_API_KEY} 从宿主环境解析出来;缺失且没有默认值时会直接报错。Agent 配置序列化会把敏感值模板化或脱敏,Agent env 的作用域只包围 setup/run,不延伸到 Verifier、构建和 Artifact 命令。21

警告:Agent 进程在其作用域内仍然能读取凭据。BaseInstalledAgent._exec() 还会把每次调用的 env 放进 DEBUG 日志记录的附加字段。不要在共享 CI 日志中开启 --debug,不要上传未经审查的 Agent 日志,也不要把真实 Key 写成 YAML 字面量。22

19.5.1 无模型、无 Docker 的静态预检

在已经安装并激活 Harbor v0.18.0 的 Python 环境中,先验证 Job、Factory、Prompt 和 CLI flags,不安装任何东西:

ANTHROPIC_API_KEY=preflight-placeholder python - <<'PY'
import os
from pathlib import Path
import yaml

from harbor.agents.factory import AgentFactory
from harbor.models.job.config import JobConfig

raw = yaml.safe_load(Path("configs/ch19-claude.yaml").read_text())
job = JobConfig.model_validate(raw)
assert job.n_concurrent_trials == 1
assert len(job.agents) == 1

agent = AgentFactory.create_agent_from_config(
job.agents[0], logs_dir=Path("/tmp/ch19-agent-logs")
)
assert agent.name() == "claude-code"
assert agent.version() == "2.1.204"
assert agent.to_agent_info().model_info.provider == "anthropic"
assert agent.to_agent_info().model_info.name == "claude-sonnet-4-5"
assert "--max-turns 12" in agent.build_cli_flags()
assert "--disallowedTools WebFetch" in agent.build_cli_flags()

rendered = agent.render_instruction("诊断服务并提交修复。")
assert "诊断服务并提交修复。" in rendered
assert "{{ instruction }}" not in rendered
print(agent.name(), agent.version())
print(agent.build_cli_flags())
PY

preflight-placeholder 只用于验证模板解析,不能发起真实请求。预期的确定性输出是 Agent 名称、固定版本以及构造出的 flags;此时不会验证包管理器、上游下载地址、模型权限或账户额度。

19.5.2 只验证安装

确认 Dataset 路径和 Docker 可用后,先执行:

export ANTHROPIC_API_KEY='<YOUR-KEY>'
harbor run \
--config configs/ch19-claude.yaml \
--install-only \
--job-name ch19-claude-install-check \
--yes

--install-only 仍会启动每个选中 Task 的环境并执行 Agent setup,但跳过 agent.run() 和 Verifier,并自动禁用验证。这里必须覆盖为独立的 job_name:Harbor 会把 install_only=true 写入保存配置,同名 Job 之后改成完整运行会因新旧 JobConfig 不相等而被拒绝。安装预检能发现操作系统、包管理器、setup 网络、用户权限和第三方版本问题,却不能证明认证有效、模型可用或 Agent 能完成任务。23

检查 jobs/ch19-claude-install-check/ 下的 Trial:

  • result.jsonagent_setup 的起止时间;
  • agent_info.nameclaude-code
  • agent_info.version2.1.204
  • 没有把“无 Reward”误判为 Task 失败,因为本次本来就没有运行 Verifier;
  • exception_info 为空,否则先修 setup,不进入付费实验。

若 Task 的环境镜像本身已经包含匹配版本,Claude Code wrapper 会先执行版本检查并跳过重装;版本不匹配才进入安装路径。这样可以把 setup 网络依赖从正式评测中移除。15

19.5.3 运行一次低并发验证

安装预检通过后,再执行完整 Job:

harbor run --config configs/ch19-claude.yaml --yes

这一步会产生真实模型费用,且结果不应预先写进书稿。验收时同时检查:

  1. config.json 与 lock 中的 Agent、模型、Prompt 来源和 Task 身份符合预注册计划;
  2. Trial 的 agent_info 保留 Agent 版本与完整 provider/model
  3. agent_setupagent_execution、Verifier 三段时间能够分开;
  4. agent/trajectory.json 通过 ATIF 校验;
  5. Reward 来自 Verifier,而不是从 Agent 最终文字猜测;
  6. exception_info、Agent 原生日志与 Reward 没有互相矛盾。

Prompt 也应纳入版本材料:

shasum -a 256 prompts/incident-agent.j2
python -m harbor.utils.trajectory_validator \
jobs/ch19-claude-controlled/<trial>/agent/trajectory.json

19.6 怎样比较两个 Agent 才算公平

公平不等于强行让所有 Agent 的配置字段看起来相同。不同 CLI 的工具系统、默认 Prompt、上下文管理和权限语义本来就是 Agent 的一部分。你需要固定的是实验问题,并清楚标出哪些差异属于处理变量。

如果问题是“Agent A 与 Agent B 在同一模型上的脚手架差异”,则必须先证明两个 wrapper 都能无损表达同一个模型和认证路径。做不到时,结论只能写成“Agent+Model 系统比较”,不能声称 Agent 因果效应。建议在开跑前冻结下列矩阵:

维度必须记录的值不一致时的处理
Harborv0.18.0 与 commit禁止合并结果
AgentFactory 名、wrapper 路径、CLI 精确版本视为 Agent 处理变量
Model完整 Provider、模型 ID、端点与认证路径不同则报告系统比较
TaskDataset ref/digest、Task checksum、容器镜像不同则重跑
Prompt模板 SHA-256、附加指令顺序不同则单列实验臂
自治预算Agent 原生轮次、Harbor timeout、金额上限解释不可完全等价之处
能力面用户、工具、MCP、Skill、网络、资源记录有效能力,不只记录参数名
采样尝试次数、并发、重试策略、时间窗口同批交错运行并保留全部 Trial

Harbor 的 n_concurrent 是每个 Agent 的 run() 并发上限,并受 n_concurrent_trials 总上限约束。它适合把 Provider 限流不同的 Agent 放进共享并发池,但限流参数本身会影响等待和失败率,应写入实验计划。24

Agent 版本也不能依赖“安装时最新”。若某个适配器不支持真正的版本固定,就预装带 digest 的环境镜像,并把镜像、实际 --version 输出和 wrapper commit 一起记录。安装时间应作为 setup 指标单独报告;能力比较至少同时给出 Agent execution 时间和端到端时间,不能把首次下载依赖的冷启动全部算成模型推理速度。

19.6.1 把有效能力写进实验清单

仅保存 Harbor 命令还不够。某个 Agent 的 allowed_tools=Read 可能表示“Read 无需确认”,另一个 Agent 的相似字段却可能表示“只允许 Read”;名称相同、语义未必相同。预注册材料应同时包含原始配置和归一化后的有效能力说明,例如:

filesystem: /app 可读写;其余只读或不可见
process: 可执行普通用户命令;无 sudo;无 Docker socket
network: 仅模型 API 与任务内服务;禁止公共 Web
tools: Read/Edit/Bash;WebFetch 禁止;原生确认已 Headless 化
mcp: 无
skills: incident-response@<content-sha256>
timeout: setup=600s;run=900s;native max_turns=12
budget: native max_budget_usd=2.00;账户侧另有限额

其中“可执行普通用户命令”必须由 Task 的 agent.user、容器 capability 和实际探针证明,不能由 Prompt 宣称。模型预算也有两个边界:CLI 的本地金额上限依赖上游计费信息,账户或网关限额由 Provider 执行;两者都不能替代 Harbor 的墙钟超时。把这份归一化清单随 Job lock 保存,审计者才能判断两个 Agent 面对的动作空间是否可比。

同批运行还应交错不同实验臂。若先把 Agent A 全部跑完,再隔数小时运行 Agent B,Provider 负载、限流、镜像缓存和任务服务状态都会与 Agent 处理变量纠缠。Harbor 会把 Agent 放在 Trial 组合的内层以便分散模型 Provider,但你仍需保存 Trial 时间、重试和基础设施异常,并在报告中给出全部计划分母,而不是只比较成功返回的样本。25

19.7 失败分类与排查顺序

内置 Agent 的失败最好按最先失效的边界分类:

阶段典型证据先检查什么
配置/创建unknown agent、缺环境变量、非法 enum 或 kwargFactory 映射、JobConfig、Agent 构造静态探针
Environment镜像构建、健康检查或 OS 不兼容异常Task OS、Provider、镜像和资源
Agent setup包管理器、DNS、权限、安装超时、版本不符环境基线网络、容器用户、固定版本、setup 日志
认证/模型401/403、模型不存在、凭据文件路径错误wrapper 的认证优先级与模型拆分规则
Agent run非零退出、API rate limit、网络错误、Agent timeout原生日志、trajectory、Harbor phase 时间
VerifierReward 缺失或测试异常Verifier 日志与候选最终状态

BaseInstalledAgent 会从非零命令的 stdout/stderr 匹配 rate limit、usage limit、API 5xx、overloaded、连接关闭、DNS、TLS 和连接失败等模式;没有匹配才回退为普通 NonZeroAgentExitCodeError。这是重试与归因的有用线索,不是完整根因证明:第三方 CLI 改写错误文本后,分类可能退化。26

单步 Trial 对 Agent timeout 或非零退出会记录异常、同步已有输出,然后仍继续运行 Verifier。于是一个 Trial 可以同时有 exception_info 和部分 Reward;不要用“有 Reward”反推 Agent 正常结束,也不要把所有异常后的零分都归因给模型。27

一个有效的排查顺序是:

  1. 重跑静态预检,排除名称、配置和 Prompt 错误;
  2. 用同一个 Task 执行 --install-only,排除环境和安装错误;
  3. 查看 result.json 中最早失败阶段及 exception_info
  4. 查 Agent 原生日志,确认认证、模型与 Headless 命令是否真正启动;
  5. 校验 trajectory,但不把缺失 trajectory 自动等同于 Agent 沉默;
  6. 最后才解释 Verifier Reward,并把重试、超时和基础设施失败保留在总分母审计中。

19.8 本章小结

  • Harbor 的内置 Agent 是版本化 wrapper,不是对任意模型和平台的兼容承诺。
  • v0.18.0 的 Factory 映射有 32 个可创建名称;terminusterminus-1 只是遗留枚举项。
  • setup 使用环境网络基线,Agent phase allowlist 不会自动解决在线安装。
  • Prompt、Agent 原生轮次、Harbor timeout 和工具权限必须分别固定与记录。
  • 三个代表性 CLI wrapper 都采用高自治 Headless 参数,真正的安全边界仍在用户、容器、网络、资源和 Verifier。
  • 先静态预检,再 --install-only,最后才进行模型调用,能避免把安装与认证错误算成能力失败。
  • 无法让两个 Agent 使用同一模型和能力面时,应报告 Agent+Model 系统比较。

19.9 练习

  1. 运行本章 Factory 探针,把 32 个名称保存为排序后的 JSON;再断言 AgentName.values() 与 Factory key 的差集恰好是 terminusterminus-1
  2. codex 编写一份只做静态构造的 Job 配置,验证缺少 model_name 会在 run() 前成为明确风险;比较 API Key 与 auth.json 两条认证路径,不上传真实凭据。
  3. 把贯穿项目 Task 的 [environment] 基线改为 none,保留 Agent phase 的模型域名 allowlist,解释为什么在线 install() 仍失败;再通过预装 Agent 的镜像消除该依赖。
  4. 设计 claude-code 与另一个 wrapper 的兼容矩阵。若不能共享完全相同的模型和认证端点,重写研究问题,使结论不再声称纯 Agent 因果差异。
  5. 构造一个 Agent 非零退出但工作区已有部分修复的教学 Task,验证 Verifier 仍可运行;报告时把异常、部分 Reward 和最终失败原因分开。

参考资料

Footnotes

  1. Harbor Framework Team,src/harbor/agents/base.py,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/base.py#L13-L167,访问于 2026-07-16。

  2. Harbor Framework Team,src/harbor/agents/factory.py,配置解析与实例创建,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/factory.py#L125-L205,访问于 2026-07-16。

  3. Harbor Framework Team,Agents 文档,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/docs/content/docs/agents/index.mdx#L13-L116,访问于 2026-07-16。

  4. Harbor Framework Team,src/harbor/agents/installed/base.py,Installed Agent 初始化、安装与版本探测,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/installed/base.py#L219-L274https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/installed/base.py#L481-L521,访问于 2026-07-16。

  5. Harbor Framework Team,Trial 创建环境与 phase 网络切换,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/trial/trial.py#L759-L785https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/trial/trial.py#L426-L450https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/models/trial/config.py#L97-L105,访问于 2026-07-16。

  6. Harbor Framework Team,AgentFactory._AGENT_MAP,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/factory.py#L24-L62,访问于 2026-07-16。

  7. Harbor Framework Team,ACP Registry Agent 文档,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/docs/content/docs/agents/acp.mdx#L7-L60,访问于 2026-07-16。

  8. Harbor Framework Team,AgentName 与 CLI Agent metavar,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/models/agent/name.py#L1-L42https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/cli/jobs.py#L51-L53,访问于 2026-07-16。

  9. Harbor Framework Team,Windows Agent 预检,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/trial/trial.py#L1114-L1138https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/tests/unit/test_agent_os_compat.py#L15-L52,访问于 2026-07-16。

  10. Harbor Framework Team,Claude Code 认证、模型与 Headless 执行,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/installed/claude_code.py#L1275-L1451,访问于 2026-07-16。 2

  11. Harbor Framework Team,Codex 认证与 Headless 执行,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/installed/codex.py#L969-L1106,访问于 2026-07-16。 2

  12. Harbor Framework Team,Gemini CLI 认证与 Headless 执行,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/installed/gemini_cli.py#L693-L851,访问于 2026-07-16。 2

  13. Anthropic,Claude Code CLI reference,https://code.claude.com/docs/en/cli-usage,访问于 2026-07-16。 2

  14. Google,Gemini CLI Headless Mode,https://google-gemini.github.io/gemini-cli/docs/cli/headless.html,访问于 2026-07-16。

  15. Harbor Framework Team,Claude Code 版本检查与安装,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/installed/claude_code.py#L136-L201,访问于 2026-07-16。 2

  16. Harbor Framework Team,render_prompt_template(),Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/utils/templating.py#L16-L70,访问于 2026-07-16。

  17. Harbor Framework Team,Claude Code CLI flag 描述符,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/installed/claude_code.py#L40-L119,访问于 2026-07-16。

  18. Harbor Framework Team,Trial timeout 计算,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/trial/trial.py#L80-L80https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/trial/trial.py#L989-L1021,访问于 2026-07-16。

  19. npm Registry,@anthropic-ai/claude-code 2.1.204 元数据,https://registry.npmjs.org/%40anthropic-ai%2Fclaude-code/2.1.204,访问于 2026-07-16。

  20. Harbor Framework Team,MCP Task 教程的 Claude Code 模型示例,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/docs/content/docs/tutorials/mcp-server-task.mdx#L128-L137,访问于 2026-07-16。

  21. Harbor Framework Team,Agent env 模板解析、序列化与作用域,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/utils/env.py#L43-L130https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/models/trial/config.py#L123-L145https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/environments/base.py#L407-L448,访问于 2026-07-16。

  22. Harbor Framework Team,Installed Agent 命令日志记录,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/installed/base.py#L403-L453,访问于 2026-07-16。

  23. Harbor Framework Team,--install-only CLI、JobConfig 与同名 Job 恢复约束,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/cli/jobs.py#L853-L862https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/cli/jobs.py#L1328-L1333https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/models/job/config.py#L434-L444https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/job.py#L200-L220,访问于 2026-07-16。

  24. Harbor Framework Team,AgentConfig 并发、超时、日志与环境字段,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/models/trial/config.py#L61-L125,访问于 2026-07-16。

  25. Harbor Framework Team,Job 的 Trial 组合顺序,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/job.py#L364-L386,访问于 2026-07-16。

  26. Harbor Framework Team,Installed Agent 错误模式与分类,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/installed/base.py#L219-L244https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/agents/installed/base.py#L380-L445,访问于 2026-07-16。

  27. Harbor Framework Team,SingleStep Trial 的 Agent 异常与 Verifier 顺序,Harbor v0.18.0 固定提交,https://github.com/harbor-framework/harbor/blob/527d50deb63a5d279e8c20593c18a2cbc7f61f9e/src/harbor/trial/single_step.py#L75-L108,访问于 2026-07-16。