$npx -y skills add vercel/ai --skill add-harness-packageGuide 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.
| 1 | ## Adding a New Harness Package |
| 2 | |
| 3 | This guide covers creating a new `@ai-sdk/harness-<name>` package for an agent harness. |
| 4 | |
| 5 | 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. |
| 6 | Prefer host-driven when the runtime supports it. |
| 7 | |
| 8 | ## First-Party vs Third-Party Harnesses |
| 9 | |
| 10 | - **Third-party packages**: Any runtime can publish an external harness package. |
| 11 | - **First-party `@ai-sdk/harness-<name>` packages**: Create an issue first to discuss whether the runtime belongs in this repo. |
| 12 | |
| 13 | ## Reference Example |
| 14 | |
| 15 | See https://github.com/vercel/ai/pull/16255/changes for a complete example of adding a new harness. |
| 16 | |
| 17 | ## Harness Architecture |
| 18 | |
| 19 | The AI SDK uses a layered harness architecture following the adapter pattern: |
| 20 | |
| 21 | 1. **Harness specification** (`@ai-sdk/harness`): Defines interfaces like `HarnessV1` and `HarnessV1Session` |
| 22 | 2. **Utilities** (`@ai-sdk/harness/utils`): Shared code for implementing harnesses |
| 23 | 3. **Harness implementations** (`@ai-sdk/harness-<name>`): Concrete adapters for harnesses |
| 24 | 4. **Harness agent** (`@ai-sdk/harness/agent`): The high-level user-facing `HarnessAgent` API |
| 25 | |
| 26 | ## Step-by-Step Guide |
| 27 | |
| 28 | ### 1. Create Package Structure |
| 29 | |
| 30 | Create `packages/harness-<name>` with this baseline structure: |
| 31 | |
| 32 | ``` |
| 33 | packages/harness-<name>/ |
| 34 | ├── src/ |
| 35 | │ ├── index.ts |
| 36 | │ ├── <name>-harness.ts |
| 37 | │ ├── <name>-harness.test.ts |
| 38 | │ └── <name>-auth.ts # if the runtime needs auth resolution |
| 39 | ├── package.json |
| 40 | ├── tsconfig.json |
| 41 | ├── tsconfig.build.json |
| 42 | ├── tsup.config.ts |
| 43 | ├── turbo.json |
| 44 | ├── vitest.node.config.js |
| 45 | └── README.md |
| 46 | ``` |
| 47 | |
| 48 | If the runtime must execute inside the sandbox, add bridge files as well: |
| 49 | |
| 50 | ``` |
| 51 | src/ |
| 52 | ├── <name>-bridge-protocol.ts |
| 53 | ├── <name>-bridge-protocol.test.ts |
| 54 | └── bridge/ |
| 55 | ├── index.ts |
| 56 | ├── package.json |
| 57 | └── pnpm-lock.yaml |
| 58 | ``` |
| 59 | |
| 60 | Add a `CHANGELOG.md` containing just the package heading (`# @ai-sdk/harness-<name>`). Every package is required to have one. |
| 61 | |
| 62 | ### 2. Configure package.json |
| 63 | |
| 64 | Use existing harness packages as the source of truth for scripts, exports, repository metadata, and publish settings. |
| 65 | |
| 66 | Required package basics: |
| 67 | |
| 68 | - `"name": "@ai-sdk/harness-<name>"` |
| 69 | - `"type": "module"` |
| 70 | - `"version": "0.0.0"` (starting point for new packages) |
| 71 | - `"license": "Apache-2.0"` |
| 72 | - `"sideEffects": false` |
| 73 | - dependency on `@ai-sdk/harness` via `workspace:*` |
| 74 | - dependency on `@ai-sdk/provider-utils` via `workspace:*` when using sandbox/auth/schema utilities |
| 75 | - runtime SDK/CLI dependencies required by the harness |
| 76 | - dev dependencies matching existing harness packages |
| 77 | - `"engines": { "node": ">=22" }` |
| 78 | |
| 79 | For bridge packages, add any bridge asset copy step required for files under `src/bridge/`. |
| 80 | |
| 81 | Bridge dependency rules (bridge-backed harnesses): |
| 82 | |
| 83 | - 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). |
| 84 | - 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. |
| 85 | - 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. |
| 86 | - 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. |
| 87 | |
| 88 | ### 3. Create TypeScript, Build, and Test Configs |
| 89 | |
| 90 | Copy the nearest existing harness package config files and adjust paths/package names: |
| 91 | |
| 92 | - `tsconfig.json` |
| 93 | - `tsconfig.build.json` |
| 94 | - `tsup.config.ts` |
| 95 | - `turbo.json` |
| 96 | - `vitest.node.config.js` |
| 97 | |
| 98 | Harness packages currently use Node tests only unless the implementation has a specific reason to add another runtime. |
| 99 | |
| 100 | ### 4. Implement the Harness Adapter |
| 101 | |
| 102 | Export a factory from `<name>-harness.ts` and re-export it from `src/index.ts`. |
| 103 | |
| 104 | Use the architecture doc for contract details. At implementation time, verify: |
| 105 | |
| 106 | - return a `HarnessV1` with `specificationVersion: 'harness-v1'`; |
| 107 | - use a stable kebab-case `harnessId`; |
| 108 | - expose adapter-native built-in tools through `builtinTools`; |
| 109 | - keep construction synchronous a |