add-harness-package

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Adding a New Harness Package

新增 Harness 包

This guide covers creating a new
@ai-sdk/harness-<name>
package for an agent harness.
A harness can be host-driven, where the runtime runs in the host process and uses the sandbox remotely, or bridge-backed, where a small bridge runs inside the sandbox because the runtime needs local access to the sandbox filesystem or process environment. Prefer host-driven when the runtime supports it.
本指南介绍如何为 Agent Harness 创建全新的
@ai-sdk/harness-<name>
包。
Harness 可分为宿主驱动型(host-driven)和桥接支撑型(bridge-backed):前者的运行时运行在宿主进程中,远程调用沙箱;后者则在沙箱内部运行一个小型桥接程序,因为运行时需要本地访问沙箱的文件系统或进程环境。若运行时支持,优先选择宿主驱动型。

First-Party vs Third-Party Harnesses

官方 Harness 与第三方 Harness

  • Third-party packages: Any runtime can publish an external harness package.
  • First-party
    @ai-sdk/harness-<name>
    packages
    : Create an issue first to discuss whether the runtime belongs in this repo.
  • 第三方包:任何运行时都可以发布外部 Harness 包。
  • 官方
    @ai-sdk/harness-<name>
    包
    :请先创建 Issue 讨论该运行时是否适合纳入本仓库。

Reference Example

参考示例

See https://github.com/vercel/ai/pull/16255/changes for a complete example of adding a new harness.
新增 Harness 的完整示例可参考:https://github.com/vercel/ai/pull/16255/changes

Harness Architecture

Harness 架构

The AI SDK uses a layered harness architecture following the adapter pattern:
  1. Harness specification (
    @ai-sdk/harness
    ): Defines interfaces like
    HarnessV1
    and
    HarnessV1Session
  2. Utilities (
    @ai-sdk/harness/utils
    ): Shared code for implementing harnesses
  3. Harness implementations (
    @ai-sdk/harness-<name>
    ): Concrete adapters for harnesses
  4. Harness agent (
    @ai-sdk/harness/agent
    ): The high-level user-facing
    HarnessAgent
    API
AI SDK 采用遵循适配器模式的分层 Harness 架构:
  1. Harness 规范(
    @ai-sdk/harness
    ):定义
    HarnessV1
    、
    HarnessV1Session
    等接口
  2. 工具库(
    @ai-sdk/harness/utils
    ):实现 Harness 所需的共享代码
  3. Harness 实现(
    @ai-sdk/harness-<name>
    ):具体的 Harness 适配器
  4. Harness Agent(
    @ai-sdk/harness/agent
    ):面向用户的高层
    HarnessAgent
    API

Step-by-Step Guide

分步指南

1. Create Package Structure

1. 创建包结构

Create
packages/harness-<name>
with this baseline structure:
packages/harness-<name>/
├── src/
│   ├── index.ts
│   ├── <name>-harness.ts
│   ├── <name>-harness.test.ts
│   └── <name>-auth.ts              # if the runtime needs auth resolution
├── package.json
├── tsconfig.json
├── tsconfig.build.json
├── tsup.config.ts
├── turbo.json
├── vitest.node.config.js
└── README.md
If the runtime must execute inside the sandbox, add bridge files as well:
src/
├── <name>-bridge-protocol.ts
├── <name>-bridge-protocol.test.ts
└── bridge/
    ├── index.ts
    ├── package.json
    └── pnpm-lock.yaml
Add a
CHANGELOG.md
containing just the package heading (
# @ai-sdk/harness-<name>
). Every package is required to have one.
创建
packages/harness-<name>
目录,基础结构如下:
packages/harness-<name>/
├── src/
│   ├── index.ts
│   ├── <name>-harness.ts
│   ├── <name>-harness.test.ts
│   └── <name>-auth.ts              # if the runtime needs auth resolution
├── package.json
├── tsconfig.json
├── tsconfig.build.json
├── tsup.config.ts
├── turbo.json
├── vitest.node.config.js
└── README.md
如果运行时必须在沙箱内执行,还需添加桥接文件:
src/
├── <name>-bridge-protocol.ts
├── <name>-bridge-protocol.test.ts
└── bridge/
    ├── index.ts
    ├── package.json
    └── pnpm-lock.yaml
添加
CHANGELOG.md
文件,内容仅需包含包标题(
# @ai-sdk/harness-<name>
)。所有包都必须有该文件。

2. Configure package.json

2. 配置 package.json

Use existing harness packages as the source of truth for scripts, exports, repository metadata, and publish settings.
Required package basics:
  • "name": "@ai-sdk/harness-<name>"
  • "type": "module"
  • "version": "0.0.0"
    (starting point for new packages)
  • "license": "Apache-2.0"
  • "sideEffects": false
  • dependency on
    @ai-sdk/harness
    via
    workspace:*
  • dependency on
    @ai-sdk/provider-utils
    via
    workspace:*
    when using sandbox/auth/schema utilities
  • runtime SDK/CLI dependencies required by the harness
  • dev dependencies matching existing harness packages
  • "engines": { "node": ">=22" }
For bridge packages, add any bridge asset copy step required for files under
src/bridge/
.
Bridge dependency rules (bridge-backed harnesses):
  • The bridge's runtime deps live in
    src/bridge/package.json
    (installed in-sandbox at bootstrap), not the main package.json. After changing them, regenerate
    src/bridge/pnpm-lock.yaml
    with
    pnpm --dir packages/harness-<name>/src/bridge install --lockfile-only --ignore-workspace
    (runnable from the repo root).
  • For every third-party import in
    src/bridge/
    , keep three things in sync: the import, the
    external
    array in
    tsup.config.ts
    , and the dep in
    src/bridge/package.json
    . A missing entry shows up only at sandbox runtime as a module-resolution error.
  • Include packages the runtime lazily imports — e.g. provider SDKs (
    @anthropic-ai/sdk
    ,
    openai
    ) resolved from the model id at runtime — even though nothing imports them directly. These fail only when a model of that provider is actually used.
  • Match shared dependency versions (transport, schema, tooling, runtime SDKs) to what the other harness packages currently use — copy from a sibling package rather than choosing your own pins. Stale pins drift from security patches and can desync from the shared bridge runtime; check the current versions at creation time.
脚本、导出配置、仓库元数据和发布设置请以现有 Harness 包为标准参考。
包的基础必填项:
  • "name": "@ai-sdk/harness-<name>"
  • "type": "module"
  • "version": "0.0.0"
    (新包的起始版本)
  • "license": "Apache-2.0"
  • "sideEffects": false
  • 通过
    workspace:*
    依赖
    @ai-sdk/harness
  • 若使用沙箱/认证/Schema 工具,需通过
    workspace:*
    依赖
    @ai-sdk/provider-utils
  • Harness 所需的运行时 SDK/CLI 依赖
  • 与现有 Harness 包一致的开发依赖
  • "engines": { "node": ">=22" }
对于桥接型包,需添加
src/bridge/
目录下文件的桥接资源复制步骤。
桥接依赖规则(桥接支撑型 Harness):
  • 桥接的运行时依赖放在
    src/bridge/package.json
    中(启动时在沙箱内安装),而非主 package.json。修改依赖后,需执行
    pnpm --dir packages/harness-<name>/src/bridge install --lockfile-only --ignore-workspace
    重新生成
    src/bridge/pnpm-lock.yaml
    (可在仓库根目录执行)。
  • 对于
    src/bridge/
    中的每一个第三方导入,需同步维护三处内容:导入语句、
    tsup.config.ts
    中的
    external
    数组,以及
    src/bridge/package.json
    中的依赖。缺少对应条目只会在沙箱运行时表现为模块解析错误。
  • 需包含运行时懒加载的包——例如根据模型 ID 在运行时解析的提供商 SDK(
    @anthropic-ai/sdk
    、
    openai
    )——即使没有直接导入它们。这些包只有在实际使用对应提供商的模型时才会报错。
  • 共享依赖(传输、Schema、工具、运行时 SDK)的版本需与其他 Harness 包当前使用的版本一致——直接从同级包复制版本号,不要自行指定。过时的版本会错过安全补丁,还可能与共享桥接运行时不同步;创建时请确认当前最新版本。

3. Create TypeScript, Build, and Test Configs

3. 创建 TypeScript、构建和测试配置

Copy the nearest existing harness package config files and adjust paths/package names:
  • tsconfig.json
  • tsconfig.build.json
  • tsup.config.ts
  • turbo.json
  • vitest.node.config.js
Harness packages currently use Node tests only unless the implementation has a specific reason to add another runtime.
复制最相近的现有 Harness 包的配置文件,并调整路径/包名:
  • tsconfig.json
  • tsconfig.build.json
  • tsup.config.ts
  • turbo.json
  • vitest.node.config.js
目前 Harness 包仅使用 Node 测试,除非实现有特殊需求才需要添加其他运行时。

4. Implement the Harness Adapter

4. 实现 Harness 适配器

Export a factory from
<name>-harness.ts
and re-export it from
src/index.ts
.
Use the architecture doc for contract details. At implementation time, verify:
  • return a
    HarnessV1
    with
    specificationVersion: 'harness-v1'
    ;
  • use a stable kebab-case
    harnessId
    ;
  • expose adapter-native built-in tools through
    builtinTools
    ;
  • keep construction synchronous and side-effect free;
  • use
    startOpts.sandboxSession
    and
    startOpts.sessionWorkDir
    ; never create a separate sandbox;
  • throw
    HarnessCapabilityUnsupportedError
    from the method that needs an unsupported runtime capability;
  • don't hardcode a default model unless the runtime technically requires one — some underlying SDKs have no default of their own. Otherwise pass the model only when the consumer configured one and leave the original SDK's default untouched; keep the session's
    modelId
    consistent with what's actually sent (don't report a model the bridge silently overrode);
  • handle the
    tools
    and
    instructions
    that
    doPromptTurn
    /
    doContinueTurn
    may receive: if the runtime can't take custom
    tools
    , throw
    HarnessCapabilityUnsupportedError
    so it's obvious rather than silently dropped; if it has no native
    instructions
    input, prepend them to the first user message (the Codex/Claude Code workaround);
  • quote interpolated paths (
    workDir
    , bridge-state dir, …) when building shell commands for
    sandbox.run
    /
    sandbox.spawn
    — they can contain spaces.
If the runtime needs in-sandbox setup, expose
getBootstrap()
.
在
<name>-harness.ts
中导出工厂函数,并在
src/index.ts
中重新导出。
契约细节请参考架构文档。实现时需确认以下事项:
  • 返回的
    HarnessV1
    需带有
    specificationVersion: 'harness-v1'
    ;
  • 使用稳定的 kebab-case 格式
    harnessId
    ;
  • 通过
    builtinTools
    暴露适配器原生的内置工具;
  • 构造过程保持同步且无副作用;
  • 使用
    startOpts.sandboxSession
    和
    startOpts.sessionWorkDir
    ;切勿创建独立的沙箱;
  • 若方法需要运行时不支持的能力,需抛出
    HarnessCapabilityUnsupportedError
    ;
  • 不要硬编码默认模型,除非运行时技术上要求——部分底层 SDK 本身没有默认模型。否则仅在使用者配置了模型时传入,保留原 SDK 的默认行为;保持会话的
    modelId
    与实际发送的内容一致(不要上报被桥接程序静默覆盖的模型);
  • 处理
    doPromptTurn
    /
    doContinueTurn
    可能收到的
    tools
    和
    instructions
    :如果运行时不支持自定义
    tools
    ,抛出
    HarnessCapabilityUnsupportedError
    ,这样问题会很明显,而不是被静默丢弃;如果运行时没有原生的
    instructions
    输入,将其拼接到第一条用户消息前面(Codex/Claude Code 的变通方案);
  • 在为
    sandbox.run
    /
    sandbox.spawn
    构建 shell 命令时,对插值路径(
    workDir
    、桥接状态目录等)加引号——路径可能包含空格。
如果运行时需要在沙箱内进行初始化,暴露
getBootstrap()
方法。

5. Implement Runtime-Specific Concerns

5. 实现运行时特定逻辑

Add only the concerns the runtime needs:
  • auth resolution — for AI Gateway support, use the central
    getAiGatewayAuthFromEnv()
    helper rather than reading env directly. This ensures both
    VERCEL_OIDC_TOKEN
    and
    AI_GATEWAY_API_KEY
    are accepted as Gateway credential. When the runtime resolves provider per model, resolve the provider from the model id and set that provider's env; if routing through the gateway, note that base-URL conventions differ per provider (e.g. an Anthropic client appends
    /v1/messages
    to a root base, an OpenAI client appends to a
    /v1
    base);
  • AI Gateway client attribution — follow the convention in existing harness packages: define a versioned client app value such as
    ai-sdk/harness-<name>/${VERSION}
    and use it for Gateway requests. Configure both
    User-Agent
    and
    x-client-app
    headers when the underlying runtime/SDK supports both; at least one of those two headers is required. If the runtime cannot set arbitrary headers directly, use the runtime-supported equivalent that produces one of those headers (e.g. an SDK client-app environment variable);
  • custom-tool schema translation — if you convert host tools' JSON Schema into the runtime's tool format, convert recursively (nested objects, array
    items
    , enums, descriptions); a flat top-level-only conversion silently drops the model's structured guidance. Passing the JSON Schema through directly, if the runtime accepts it, avoids the problem;
  • skill or discovery-file materialization;
  • native protocol to harness stream/control translation;
  • lifecycle state schema;
  • bridge protocol and diagnostics.
Certain structural conventions for harness adapters are being enforced via the
konsistent
CLI. Run
pnpm konsistent
once you're done to check for those. Fix any violations flagged before proceeding.
仅添加运行时需要的逻辑:
  • 认证解析——如需支持 AI Gateway,请使用中央
    getAiGatewayAuthFromEnv()
    辅助函数,而非直接读取环境变量。这样可确保
    VERCEL_OIDC_TOKEN
    和
    AI_GATEWAY_API_KEY
    都能作为 Gateway 凭证被接受。当运行时按模型解析提供商时,从模型 ID 解析提供商,并设置对应提供商的环境变量;如果通过 Gateway 路由,请注意不同提供商的 base URL 约定不同(例如 Anthropic 客户端会在根 base URL 后追加
    /v1/messages
    ,而 OpenAI 客户端会追加到
    /v1
    基础路径后);
  • AI Gateway 客户端标识——遵循现有 Harness 包的约定:定义带版本的客户端应用值,例如
    ai-sdk/harness-<name>/${VERSION}
    ,并用于 Gateway 请求。如果底层运行时/SDK 支持,同时配置
    User-Agent
    和
    x-client-app
    头;至少需要配置其中一个。如果运行时无法直接设置任意请求头,请使用运行时支持的等效方式来生成其中一个头(例如 SDK 的客户端应用环境变量);
  • 自定义工具 Schema 转换——如果你需要将宿主工具的 JSON Schema 转换为运行时的工具格式,请递归转换(嵌套对象、数组
    items
    、枚举、描述);仅做顶层的扁平转换会静默丢失模型的结构化引导信息。如果运行时支持直接传入 JSON Schema,直接透传即可避免该问题;
  • Skill 或发现文件的物化;
  • 原生协议到 Harness 流/控制的转换;
  • 生命周期状态 Schema;
  • 桥接协议与诊断信息。
Harness 适配器的部分结构约定通过
konsistent
CLI 强制校验。完成实现后运行
pnpm konsistent
检查,修复所有标记的违规项后再继续。

6. Write Tests

6. 编写测试

Add focused Node tests for:
  • factory metadata and settings;
  • auth resolution;
  • sandbox usage and path placement;
  • host-driven remote operations or bridge protocol behavior;
  • prompt/control event translation;
  • resume session vs continue turn behavior;
  • unsupported capability errors;
  • skill materialization, if supported.
Use mocked sandbox sessions and bridge/runtime boundaries where possible. Do not require live provider credentials in unit tests.
getBootstrap()
reads the compiled bridge assets (e.g.
dist/bridge/index.mjs
), which don't exist when tests run against
src
, so a test that calls it will hit
ENOENT
. Mock
node:fs/promises
readFile
for the bridge asset paths (see the Codex/OpenCode harness tests for the pattern).
添加针对性的 Node 测试,覆盖以下场景:
  • 工厂元数据与设置;
  • 认证解析;
  • 沙箱使用与路径放置;
  • 宿主驱动型远程操作或桥接协议行为;
  • 提示/控制事件转换;
  • 恢复会话 vs 继续轮次的行为;
  • 不支持能力的错误;
  • Skill 物化(如支持)。
尽可能使用模拟的沙箱会话和桥接/运行时边界。单元测试不需要真实的提供商凭证。
getBootstrap()
会读取_编译后的_桥接资源(例如
dist/bridge/index.mjs
),而测试针对
src
运行时这些文件不存在,因此调用它的测试会报
ENOENT
错误。请为桥接资源路径模拟
node:fs/promises
的
readFile
方法(模式可参考 Codex/OpenCode Harness 的测试)。

7. Add README

7. 添加 README

Keep README short:
  • package purpose;
  • setup command;
  • minimal
    HarnessAgent
    usage;
  • required sandbox capabilities, such as ports for bridge-backed runtimes;
  • notable auth configuration.
Link to the main harness docs for broader concepts.
README 保持简洁:
  • 包的用途;
  • 安装命令;
  • 最简
    HarnessAgent
    使用示例;
  • 所需的沙箱能力,例如桥接支撑型运行时需要的端口;
  • 重要的认证配置。
更广泛的概念请链接到 Harness 主文档。

8. Add Examples

8. 添加示例

Add relevant examples for the new harness.
  • Add API/function examples under
    examples/ai-functions
    when the harness package needs a scriptable provider-behavior example.
  • Add interactive examples mirroring the existing harness examples in
    examples/harness-e2e-next
    (Next.js) and
    examples/harness-e2e-tui
    (TUI).
为新 Harness 添加相关示例。
  • 当 Harness 包需要可脚本化的提供商行为示例时,在
    examples/ai-functions
    下添加 API/函数示例。
  • 在
    examples/harness-e2e-next
    (Next.js)和
    examples/harness-e2e-tui
    (TUI)中添加与现有 Harness 示例对应的交互式示例。

9. Add Documentation

9. 添加文档

Create documentation in
content/providers/02-ai-sdk-harnesses/<next number>-<name>.mdx
.
Include:
  • Setup instructions
  • Required sandbox capabilities
  • Authentication configuration
  • Harness-specific options
  • Usage examples
  • Known limitations
Update
content/docs/03-ai-sdk-harnesses/05-harness-adapters.mdx
to list the new harness when it is ready to be public.
在
content/providers/02-ai-sdk-harnesses/<next number>-<name>.mdx
中创建文档。
包含内容:
  • 安装说明
  • 所需沙箱能力
  • 认证配置
  • Harness 特定选项
  • 使用示例
  • 已知限制
当新 Harness 准备好公开发布时,更新
content/docs/03-ai-sdk-harnesses/05-harness-adapters.mdx
,将其加入列表。

10. Update References and Validate

10. 更新引用并验证

Run from the workspace root:
bash
pnpm konsistent
pnpm update-references
pnpm --filter @ai-sdk/harness-<name> build
pnpm --filter @ai-sdk/harness-<name> test
pnpm type-check:full
Add a changeset with
pnpm changeset
. For a brand-new harness package's first release, use
major
(not the usual
patch
), matching the other harness packages.
Run relevant harness examples against a live sandbox early — don't rely on unit tests and
type-check
alone. Runtime API constraints (e.g. unexpected config-option rejections, the exact streaming event names the runtime emits, gateway base-URL format) surface only when the bridge actually drives the runtime, and they're far cheaper to find before the docs/examples are built on top.
在工作区根目录执行:
bash
pnpm konsistent
pnpm update-references
pnpm --filter @ai-sdk/harness-<name> build
pnpm --filter @ai-sdk/harness-<name> test
pnpm type-check:full
使用
pnpm changeset
添加变更集。全新 Harness 包的首次发布请使用
major
版本(而非通常的
patch
),与其他 Harness 包保持一致。
尽早在真实沙箱上运行相关 Harness 示例——不要仅依赖单元测试和
type-check
。运行时 API 的限制(例如意外的配置选项拒绝、运行时发出的具体流事件名称、Gateway base URL 格式)只有在桥接程序实际驱动运行时时才会显现,在文档/示例构建完成前发现这些问题成本要低得多。

Checklist

检查清单

  • Package structure created in
    packages/harness-<name>
  • package.json
    configured with correct dependencies
  • TypeScript configs set up (
    tsconfig.json
    ,
    tsconfig.build.json
    )
  • Build configuration (
    tsup.config.ts
    )
  • Test configuration (
    vitest.node.config.js
    )
  • Harness adapter implementation complete
  • Runtime placement handled without creating a hidden sandbox
  • Bridge assets copied during build, if bridge-backed
  • Auth resolution implemented, if needed
  • AI Gateway requests include
    User-Agent
    and/or
    x-client-app
    client attribution
  • Harness infra, skills, bridge code, and secrets kept out of
    sessionWorkDir
  • Session resume and turn continuation tested
  • Unit tests written and passing
  • README.md written
  • CHANGELOG.md
    added (package heading; required by
    konsistent
    )
  • Changeset added (
    major
    for a first release)
  • Examples added
  • Documentation added in
    content/providers/02-ai-sdk-harnesses/
  • Harness adapter list updated, if public
  • Validated against a live sandbox (not just unit tests / type-check)
  • pnpm update-references
    run
  • Package build passing
  • Package tests passing
  • Type checking passing (
    pnpm type-check:full
    from root)
  • Relevant examples run successfully
  • 已在
    packages/harness-<name>
    中创建包结构
  • package.json
    已配置正确的依赖
  • TypeScript 配置已设置(
    tsconfig.json
    、
    tsconfig.build.json
    )
  • 构建配置(
    tsup.config.ts
    )
  • 测试配置(
    vitest.node.config.js
    )
  • Harness 适配器实现完成
  • 运行时放置处理正确,未创建隐藏沙箱
  • 如为桥接支撑型,构建时会复制桥接资源
  • 已实现认证解析(如需要)
  • AI Gateway 请求包含
    User-Agent
    和/或
    x-client-app
    客户端标识
  • Harness 基础设施、Skill、桥接代码和密钥未放入
    sessionWorkDir
  • 会话恢复和轮次续跑已测试
  • 单元测试已编写且通过
  • README.md 已编写
  • 已添加
    CHANGELOG.md
    (包标题;
    konsistent
    强制要求)
  • 已添加变更集(首次发布使用
    major
    )
  • 已添加示例
  • 已在
    content/providers/02-ai-sdk-harnesses/
    中添加文档
  • 如公开,已更新 Harness 适配器列表
  • 已在真实沙箱上验证(而非仅单元测试/类型检查)
  • 已运行
    pnpm update-references
  • 包构建通过
  • 包测试通过
  • 类型检查通过(根目录执行
    pnpm type-check:full
    )
  • 相关示例运行成功

Related Documentation

相关文档

  • Harness Abstraction Architecture
  • @ai-sdk/harness
    README
  • Existing harness packages with similar runtime placement
  • Harness 抽象架构
  • @ai-sdk/harness
    README
  • 运行时放置方式相似的现有 Harness 包