主题
Harbor 集成
在 LangSmith 上用 Harbor 运行评估、Deep Agents 和沙箱。
用 LangSmith 从一个地方运行、追踪、比较并为 agent 评估计费,以 Harbor 作为执行层。Harbor 是一个用于在沙箱环境中评估和优化 agent 与语言模型的框架,出自 Terminal-Bench 的创作者。它在隔离容器中运行每次试验,因此你能同时对许多环境并行评估和推演。
LangSmith 在三个接入点与 Harbor 集成:
- LangSmith 评估:用
--plugin langsmith把每个 Harbor 作业记录到 LangSmith 作为一个实验。 - Deep Agents:用
--agent langgraph把一个 LangGraph 或 Deep Agents 应用作为 Harbor agent 运行。 - 沙箱:用
--env langsmith在 LangSmith 沙箱上运行每个 Harbor 试验。
本页涵盖 LangSmith 专属的 Harbor 标志。有关完整的 CLI,运行 harbor run --help 或参阅 Harbor 文档。
前置条件
- 一个 LangSmith 账户和一个 API 密钥。
- 带
pip的 Python 3.12 或更高版本。 - 你的 agent 所调用模型的一个提供商 API 密钥,例如
ANTHROPIC_API_KEY。
安装
用 langsmith extra 安装 Harbor。该 extra 包含了 LangSmith 插件、环境和 agent 所使用的 harbor-langsmith 包:
bash
pip install "harbor[langsmith]"身份验证
Harbor 用你的 LangSmith 凭据进行身份验证。设置一个 API 密钥和该密钥所属的端点:
bash
export LANGSMITH_API_KEY="<LANGSMITH_API_KEY>"
export LANGSMITH_ENDPOINT="<LANGSMITH_ENDPOINT>"LANGSMITH_ENDPOINT 默认为 https://api.smith.langchain.com(GCP US)。在 BYOC 上把它设为你的数据平面 URL,在自托管上设为你的实例 URL,或在其他 Cloud 区域上设为你所在区域的 API URL。
或者,改选一个 LangSmith SDK 配置文件而非导出一个密钥:
bash
export LANGSMITH_PROFILE=prod快速开始
把一个 Harbor 作业作为实验记录到 LangSmith:
bash
harbor run -d "terminal-bench@2.0" \
--agent <agent> \
--model <provider:model> \
--plugin langsmith把 <agent> 替换为一个 Harbor agent,把 <provider:model> 替换为一个 provider:model 格式、已安装的 langchain-* 提供商可解析的模型,例如 anthropic:claude-opus-4-8。运行 harbor run --help 列出可用的 agent,或参阅 Deep Agents 获取一个完整的 langgraph 运行。
打开数据集与实验,选择 Harbor 同步的数据集,例如 terminal-bench@2.0,然后打开 Experiments 标签查看该运行。
LangSmith 评估
LangSmith 插件把每个 Harbor 作业记录到 LangSmith,因此你能在数据集与实验下查看并比较结果。该插件适用于任何 Harbor agent,不仅是 Deep Agents。用 --plugin langsmith 启用它。快速开始展示了基本的调用,本节涵盖插件记录了什么以及如何配置它。
选择一个会追踪到 LangSmith 的 agent,以便在实验旁捕获完整的 agent 追踪。如果该 agent 不追踪到 LangSmith,插件仍会创建数据集和实验,带上结果和反馈,只是没有 agent 追踪。
当你需要消除歧义时,传入完整的导入路径而非短的插件名:
bash
harbor run ... --plugin harbor_langsmith:LangSmithPlugin该插件需要 LANGSMITH_API_KEY。
查看插件记录了什么
随着作业运行,插件通过 API 写入 LangSmith:
- 数据集:从作业同步一个参考数据集。默认名来自数据集或任务,例如
terminal-bench@2.0。每个任务成为一个示例,其输入是任务名、指令和任务 ID。 - 实验:为每个作业创建一个实验,命名为
<name>-<job-id-prefix>,链接到参考数据集。 - 运行:为每次试验创建一个根运行,其输入是任务名、指令、agent 和模型,外加环境、agent 和验证阶段的子运行。
- 反馈:为每个验证器奖励键(例如
reward)附加一个反馈分数,并在某次试验抛出异常时附加一个harbor_error反馈。 - 输出:在每次试验运行中,把 token 计数记录在
tokens(input、cache、output)下,把运行成本记录在cost_usd下。
在 LangSmith 中查看结果
在 LangSmith 中打开数据集与实验,选择插件同步的数据集,例如 terminal-bench@2.0,然后打开 Experiments 标签。每个 Harbor 作业显示为一个实验,你可以按 reward 和 harbor_error 反馈、记录在每次运行上的 token 计数和成本,以及延迟来比较实验。
配置插件输入
插件先从构造关键字参数读取每个输入,然后回退到一个环境变量。用环境变量设置输入:
HARBOR_LANGSMITH_DATASET:数据集名。默认为从作业派生的名称。HARBOR_LANGSMITH_EXPERIMENT:实验基名。默认为作业名。LANGSMITH_ENDPOINT:LangSmith API 端点。默认为https://api.smith.langchain.com。LANGSMITH_WORKSPACE_ID:目标工作区。HARBOR_LANGSMITH_SYNC_DATASET:设为false以禁用数据集和示例同步。HARBOR_LANGSMITH_FAIL_FAST:设为true以在 LangSmith API 出错时抛出,而非继续作业。
或者用命令行上的 --pk 或作业配置文件 kwargs: 下,作为插件 kwargs 设置同样的输入。这些 kwargs 对应构造选项:dataset_name、experiment_name、endpoint、api_key、workspace_id、sync_dataset 和 fail_fast。
Deep Agents
langgraph agent 把一个 LangGraph 应用(例如一个 Deep Agent)作为 Harbor agent 运行。用 --agent langgraph 选择它。Harbor 会把你的项目暂存到沙箱中,安装其依赖,并在每次试验中于容器内运行该图。
设置你的 LangSmith 和模型凭据,然后运行 Harbor。harbor run 是 harbor job start 的别名,它会构建一个作业、启动环境并运行 LangGraph agent:
bash
export LANGSMITH_PROFILE=prod
export LANGSMITH_TRACING=true
export LANGSMITH_PROJECT=harbor-deepagents
export FIREWORKS_API_KEY="<FIREWORKS_API_KEY>"
harbor run \
-t hello-world/hello-world \
--agent langgraph \
--model fireworks:accounts/fireworks/models/glm-5p2 \
--ak project_path=./deep-agent \
--ak graph=deep_agent选择评估的对象
一个任务是一个带固定布局的目录:task.toml 放配置,instruction.md 放提示,environment/ 放构建沙箱所用的 Dockerfile,tests/ 放写奖励的验证器。一个数据集是许多这样的任务目录。
一个任务或数据集可以是本地或远程的:把 Harbor 指向你自己的一文件夹任务目录,或从 Harbor 的注册表拉取一个。
三个输入选择作业所针对运行的任务:
-t org/name[@ref]:注册表中的一个单一任务。远程任务通过注册表查找被获取,然后克隆到~/.cache/harbor/tasks中固定的 commit。-d name@version:整个基准数据集,即许多任务。每个任务从注册表解析并克隆到缓存。-p <dir>:一个本地路径,指向一个任务或许多任务的根文件夹。本地路径就地读取,不下载、不缓存副本。
用 -i 和 -x(glob 包含与排除)过滤所选任务,并用 -l 限制数量。
一个任务目录有如下布局:
text
hello-world/
├── task.toml # timeouts, CPU, and memory
├── instruction.md # the prompt given to the agent
├── environment/
│ └── Dockerfile # image the sandbox is built from
├── tests/
│ ├── test.sh # writes the reward to /logs/verifier/reward.txt
│ └── test_state.py # the assertions
└── solution/ # optional, used only by the oracle agent一个数据集是一个任务目录的目录:
text
terminal-bench/
├── hello-world/ # each subdirectory is a full task
├── fix-bug/ # (task.toml + instruction.md + environment/ + tests/)
└── parse-csv/配置 agent
用 --ak 传入 agent kwargs:
--agent langgraph:选择 LangGraph agent。--model <provider:model>:要运行的模型。没有默认值,因此该值是必需的。agent 用 init_chat_model 解析它,因此它必须能被某个已安装的langchain-*提供商按provider:model格式解析,例如anthropic:claude-opus-4-8。一个provider/model值会被规范化为provider:model。模型来自configurable['model']或HARBOR_MODEL环境变量,一个无法解析或缺失的值会抛出ValueError。--ak project_path=<dir>:包含langgraph.json的本地目录。--ak graph=<name>:要运行langgraph.json中的哪个图。--ak config=<file>:project_path内声明那些图的配置文件名。默认为langgraph.json。--ak configurable='{...}':LangGraph 每次运行的配置,传给config["configurable"]并在调用时被图读取。常见键有model、model_kwargs和cwd。--ak model_kwargs='{...}':configurable中嵌套model_kwargs键的简写,例如{"temperature": 0, "max_tokens": 8000}。--ak dependency_overrides='[...]':用于 agent 虚拟环境的 Pip 包。这个列表替换langgraph.json中声明的依赖,让你无需编辑项目就能固定或替换版本,例如'["deepagents==0.6.10"]'。
让 langgraph.json 指向 agent 和依赖
agent 从 project_path 中的 langgraph.json 文件加载图。该文件声明图的入口点,以及 Harbor 在沙箱虚拟环境中安装的 pip 依赖:
json
{
"dependencies": [
"deepagents>=0.6.10,<0.7.0",
"langchain-anthropic>=1.4.6,<1.5.0",
"langchain-openai>=1.3.0,<1.4.0"
],
"graphs": {
"deep_agent": "./agent.py:make_graph",
"research_agent": "./agent.py:make_research_graph"
}
}该项目暴露两个图,用 --ak graph 选择。两者都用 create_deep_agent 构建一个 Deep Agent,仅输入不同:
deep_agent解析到make_graph,一个仅用模型创建的 Deep Agent。research_agent解析到make_research_graph,同一个 Deep Agent 加上一个研究系统提示。
每个图把来自 --model(从 configurable.model 读取)的模型传给 create_deep_agent,后者用 init_chat_model() 解析它:
python
from deepagents import create_deep_agent
def make_graph(config):
return create_deep_agent(model=config["configurable"]["model"])
def make_research_graph(config):
return create_deep_agent(
model=config["configurable"]["model"],
system_prompt="You are a research assistant.",
)一个读取 configurable.model 的工厂函数能让图与模型无关,但当它应当始终运行同一个模型时,你也可以在图中硬编码模型。对于固定模型,把 langgraph.json 指向一个已编译的图而非工厂:
python
from deepagents import create_deep_agent
graph = create_deep_agent(model="fireworks:accounts/fireworks/models/glm-5p2")在沙箱内运行 agent
Harbor 在整个试验容器内运行 agent。
单试验生命周期
- 解析与准备:
harbor run把标志解析为一个作业配置。作业工厂解析并缓存任务、校验环境资源限制,并在任何试验运行之前解析指标。缓存只适用于远程任务,因此一个-p本地任务是就地读取的。 - 扇出:Harbor 从
n_attempts × tasks × agents构建试验列表,然后并发运行试验,最多到-n限制,带-r次重试。并行度以每个试验为单位,因此不同的任务、agent 和尝试会一起运行,各自在自己的沙箱中。 - 创建试验:试验加载缓存的任务,从
project_path、graph和model构建 LangGraph agent,并构造环境但不启动它。 - 启动环境:环境启动并带起容器。对于 Docker 环境,这会构建或复用镜像并运行容器。
- 安装 agent:Harbor 在容器内创建一个虚拟环境,上传
project_path,并在容器内 pip 安装langgraph.json依赖。 - 运行与验证:Harbor 通过 LangGraph runner 在容器内运行图,然后运行
tests/test.sh,它把奖励写到/logs/verifier/reward.txt。 - 收尾:Harbor 停止并删除容器,并写入试验结果。作业把所有试验结果聚合为一个作业结果。
有关构建 Deep Agents 的更多信息,参阅 Deep Agents 文档。
沙箱
langsmith Harbor 环境在 LangSmith 沙箱上运行每次试验。用 --env langsmith 选择它,以在其他沙箱提供商之外,在 LangSmith 基础设施上执行 Harbor 作业。每次试验得到它自己的沙箱,Harbor 在试验结束时删除它。
运行一次评估
运行一个 Harbor 作业并用 --env langsmith 选择 LangSmith 环境:
bash
harbor run -d "<org/name>" \
--model "<model>" \
--agent "<agent>" \
--env langsmith \
-n "<n-parallel-trials>"Harbor 为每次试验创建一个 LangSmith 沙箱,并在其中运行 agent 和验证器。
配置沙箱环境
LangSmith 环境从一个文件系统快照启动每个沙箱。在你的 Harbor 任务中提供以下之一:
- 预构建镜像:在
task.toml中设置[environment].docker_image。Harbor 从那个镜像复用或创建一个快照。 - 现有快照:传入
environment.kwargs.snapshot_name,以从一个你已创建的快照启动。 - Dockerfile:包含一个
environment/Dockerfile。Harbor 用从 Dockerfile 构建快照的流程从它构建一个快照,把任务environment/目录用作构建上下文。
用环境 kwargs 调优沙箱生命周期,在命令行上用 --ek 传入:
bash
harbor run -d "<org/name>" \
--model "<model>" \
--agent "<agent>" \
--env langsmith \
-n "<n-parallel-trials>" \
--ek idle_ttl_seconds=0 \
--ek delete_after_stop_seconds=7200idle_ttl_seconds:在这些秒数的空闲之后停止一个沙箱。设为0以禁用空闲超时。delete_after_stop_seconds:在停止后这些秒数删除一个已停止的沙箱。
故障排查
- 作业因身份验证错误无法启动:确认
LANGSMITH_API_KEY已设置,或LANGSMITH_PROFILE指向一个已配置的配置文件。 - agent 为模型抛出
ValueError:以provider:model格式传入--model,并安装匹配的langchain-*提供商包,使init_chat_model()能解析它。