Catalog
vercel/add-harness-package

vercel

add-harness-package

Guide for adding new AI SDK harness packages. Use when creating a new @ai-sdk/harness-<name> package that adapts a coding-agent runtime to HarnessV1.

NewUpdated Oct 29, 2026

Adding a New Harness Package

This guide covers creating a new @ai-sdk/harness-<name> package for an agent harness.

Before evaluating a runtime, read Harness Requirements for feasibility criteria and capability gaps to document. Follow the requirements while implementing the harness package.

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.

First-Party vs Third-Party Harnesses

  • 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.

Reference Example

See https://github.com/vercel/ai/pull/16255/changes for a complete example of adding a new harness.

Harness Architecture

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

Step-by-Step Guide

1. Create Package Structure

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
├── tsdown.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.

2. Configure 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, ensure all bridge assets under src/bridge/ are copied into dist/bridge/ and can be read from there. This encompasses two steps:

  • Include a copy-bridge-assets script in the harness package's package.json. Critical: src/bridge/pnpm-lock.yaml must be copied as dist/bridge/pnpm-lockfile.yaml! It's necessary because PNPM 12's pnpm pack unconditionally excludes files named pnpm-lock.yaml.
    • Example for bridge with package.json, pnpm-lock.yaml, pnpm-workspace.yaml: "copy-bridge-assets": "node -e \"import('node:fs/promises').then(async fs => { await fs.copyFile('src/bridge/package.json', 'dist/bridge/package.json'); await fs.copyFile('src/bridge/pnpm-lock.yaml', 'dist/bridge/pnpm-lockfile.yaml'); await fs.copyFile('src/bridge/pnpm-workspace.yaml', 'dist/bridge/pnpm-workspace.yaml'); })\""
    • Example for bridge with package.json, pnpm-lock.yaml: "copy-bridge-assets": "node -e \"import('node:fs/promises').then(async fs => { await fs.copyFile('src/bridge/package.json', 'dist/bridge/package.json'); await fs.copyFile('src/bridge/pnpm-lock.yaml', 'dist/bridge/pnpm-lockfile.yaml'); })\""
  • Ensure the harness's bootstrap code defines const readBridgeAsset = createReadBridgeAsset();, using the createReadBridgeAsset function from @ai-sdk/harness/utils. In that function call, provide the map of bridge file names and where to read them from. The special case for reading pnpm-lock.yaml from the dist folder's pnpm-lockfile.yaml must be considered here as well.
    • Example for package.json: 'package.json': new URL('./bridge/package.json', import.meta.url)
    • Example for pnpm-lock.yaml: 'pnpm-lock.yaml': new URL('./bridge/pnpm-lockfile.yaml', import.meta.url)

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/, add the dependency to src/bridge/package.json so it is installed in the sandbox. tsdown automatically externalizes dependencies, peer dependencies, and optional dependencies declared by the main package; add bridge-only dependencies that are not declared there to deps.neverBundle in tsdown.config.ts. A missing dependency or required exclusion may show 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 — in src/bridge/package.json even though nothing imports them directly. They do not need a neverBundle entry unless the bridge source imports them. 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.
  • ACP adapters built on @ai-sdk/harness-acp with an npm-locked source install their src/bridge/package.json in place of the harness-acp bridge manifest. That manifest must declare every dependency of packages/harness-acp/src/v1/bridge/package.json at the same version, and the adapter's manifest path must be added to acpNpmLockedBridgeManifestPaths in tools/verify-harness-adapter-deps.mjs.

3. Create TypeScript, Build, and Test Configs

Copy the nearest existing harness package config files and adjust paths/package names:

  • tsconfig.json
  • tsconfig.build.json
  • tsdown.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.

4. Implement the Harness Adapter

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().

5. Implement Runtime-Specific Concerns

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.

6. Write Tests

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).

7. Add 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.

8. Add Examples

Add relevant examples for the new harness.

  • Add required API/function examples under examples/ai-functions/src/harness-agent and interactive examples under examples/harness-e2e-next.

9. Add Documentation

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.

10. Update References and Validate

Run from the workspace root:

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.

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 (tsdown.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
Files2
2 files · 4.7 KB

Select a file to preview

Overall Score

88/100

Grade

A

Excellent

Grades are signals, not a certification. Always review a skill yourself before use.

Safety

90

Quality

88

Clarity

87

Completeness

85

Summary

This skill guides developers through creating new `@ai-sdk/harness-<name>` packages that adapt coding-agent runtimes to the HarnessV1 specification. It provides a structured 10-step process covering package scaffolding, TypeScript/build configuration, adapter implementation, testing, documentation, and validation. The skill operates entirely within the Vercel AI SDK repository and includes detailed architectural guidance, configuration templates, and a comprehensive checklist.

Detected Capabilities

file creationdirectory structure scaffoldingconfiguration file generationTypeScript project setuppackage.json managementbuild script writingtest configurationdocumentation generationcode examples creationrepository-scoped file operations

Trigger Keywords

Phrases that agents use to match this skill to user intent.

create harness adapterharness-v1 implementationruntime integrationnew harness packagebridge-backed harnesshost-driven harnessai-sdk harness

Risk Signals

INFO

Instruction to run arbitrary Node.js eval in package.json scripts (copy-bridge-assets)

Step 2, copy-bridge-assets script example
INFO

File copying via eval in package.json

Step 2, bridge assets copy commands
INFO

Reference to externally maintained GitHub PR as implementation example

Reference Example section

Referenced Domains

External domains referenced in skill content, detected by static analysis.

github.comwww.apache.org

Use Cases

  • Create a new harness adapter for an unsupported runtime
  • Scaffold a host-driven or bridge-backed harness package
  • Implement runtime-to-HarnessV1 protocol translation
  • Set up build and test infrastructure for a harness package
  • Configure authentication, tool schema translation, and Gateway client attribution for a new harness
  • Add examples and documentation for a new harness adapter

Quality Notes

  • Comprehensive step-by-step guide with clear progression and multiple reference points
  • Well-structured with separate sections for host-driven vs bridge-backed concerns
  • Extensive checklist (25 items) ensures nothing is missed
  • Good separation of 'must have', 'should have', and 'nice to have' requirements in linked requirements doc
  • Provides concrete code examples for package.json, tsconfig, and bridge asset handling
  • Security consideration: explicitly guides against hardcoding models and emphasizes auth resolution patterns
  • Bridge dependency management is detailed with specific regeneration commands
  • Includes validation step with konsistent CLI and live sandbox testing recommendation
  • README kept deliberately short per documented convention
  • File placement and path quoting guidance prevents common shell script errors
  • Related documentation links provide architectural context
  • Specifies that tests must not require live provider credentials
  • Warns about `getBootstrap()` requiring compiled assets and provides mock pattern
Model: claude-haiku-4-5-20251001Analyzed: Oct 29, 2026

Reviews

Add this skill to your library to leave a review.

No reviews yet

Be the first to share your experience.

Version History

  1. v1.6

    Content updated

    ✦ AIExpands bridge asset copy instructions with mandatory pnpm-lockfile.yaml rename and harness bootstrap setup examples.

    2026-10-29

    LATEST
  2. v1.5

    Content updated

    ✦ AIAdds requirement for ACP adapters with npm-locked sources to declare harness-acp bridge dependencies and register manifest path in verify tool.

    2026-10-21

    View This Version
  3. v1.4

    Content updated

    ✦ AIReplaces tsup with tsdown for build config; changes external-dependency handling to use `deps.neverBundle` instead of explicit `external` array.

    2026-09-30

    View This Version
  4. v1.3

    Content updated

    ✦ AIAdds required preliminary reference check to harness-requirements.md and consolidates example paths to specific directories.

    2026-09-26

    View This Version
  5. v1.2

    Content updated

    ✦ AIAdds AI Gateway client attribution requirements:User-Agent/x-client-app headers using versioned client app format.

    2026-09-09

    View This Version
  6. v1.1

    Content updated

    ✦ AIAdds detailed bridge dependency management rules, tool/instruction handling requirements, auth gateway helper usage, and shell-quoting guidance for sandbox paths. Introduces konsistent validation ste…

    2026-06-28

    View This Version
  7. v1.0

    2026-06-18

    View This VersionInitial version

Use vercel/add-harness-package in your dev environment

Command Palette

Search for a command to run...