# Add Harness Package > Guide for adding new AI SDK harness packages. Use when creating a new @ai-sdk/harness- package that adapts a coding-agent runtime to HarnessV1. Source: https://skillsagentes.com/skills/vercel/ai/add-harness-package Repository: https://github.com/vercel/ai Author: vercel License: NOASSERTION Updated: el mes pasado Context cost: 37 tok installed, 3.1k tok once triggered, 3.1k tok with every bundled file Bundle: 1 file, 12 KB Permissions requested: none declared ## Install ```bash npx -y skills add vercel/ai --skill add-harness-package --agent claude-code ``` ## What it does - Guía paso a paso para crear un paquete @ai-sdk/harness- que adapte un runtime de agente a HarnessV1 - Define la estructura de carpetas, configuración de package.json, tsconfig, tsup y turbo requeridas - Detalla la implementación del adaptador (HarnessV1), autenticación, atribución de AI Gateway y traducción de esquemas de herramientas - Especifica tests, README, ejemplos, documentación y checklist de validación con konsistent y changesets ## Use it when - Al crear un nuevo paquete @ai-sdk/harness- que adapte un runtime de coding-agent a HarnessV1 ## What triggers it - "Quiero crear un nuevo paquete @ai-sdk/harness- para este runtime" - "Ayúdame a adaptar este agente de código a HarnessV1" - "¿Cómo estructuro un nuevo harness package en el repo de AI SDK?" ## Before you install - Se recomienda abrir primero un issue para paquetes first-party y usar paquetes harness existentes como referencia de configuración. - Needs on PATH: pnpm ## Files - SKILL.md — 12 KB ## SKILL.md Reproduced verbatim from vercel/ai under NOASSERTION. This section is the upstream document and is in English. ## Adding a New Harness Package This guide covers creating a new `@ai-sdk/harness-` 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-` 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-`): 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-` with this baseline structure: ``` packages/harness-/ ├── src/ │ ├── index.ts │ ├── -harness.ts │ ├── -harness.test.ts │ └── -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/ ├── -bridge-protocol.ts ├── -bridge-protocol.test.ts └── bridge/ ├── index.ts ├── package.json └── pnpm-lock.yaml ``` Add a `CHANGELOG.md` containing just the package heading (`# @ai-sdk/harness-`). 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-"` - `"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-/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 `-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-/${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 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). ### 9. Add Documentation Create documentation in `content/providers/02-ai-sdk-harnesses/-.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: ```bash pnpm konsistent pnpm update-references pnpm --filter @ai-sdk/harness- build pnpm --filter @ai-sdk/harness- 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-` - [ ] `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 ## Related Documentation - [Harness Abstraction Architecture](../../architecture/harness-abstraction.md) - [`@ai-sdk/harness` README](../../packages/harness/README.md) - Existing harness packages with similar runtime placement --- Skills Agentes — https://skillsagentes.com/skills/vercel/ai/add-harness-package