Skip to content
Development
Skill

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

From plugin
vercel-ai
26k12 skills
Install
$ npx -y skills add vercel/ai --skill add-harness-package --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/add-harness-package

Context preview

The summary Claude sees to decide when to auto-load this skill.

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.

SKILL.md

add-harness-package.SKILL.md
name: add-harness-package
description: 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.
metadata:
  internal: true

Adding a New Harness Package

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.

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

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

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

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 shel
Read more
Ships withvercel-ai

The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents

Get the whole plugin