Añadir un Nuevo Paquete de Harness
Esta guía cubre la creación de un nuevo paquete @ai-sdk/harness-<nombre> para un harness de agente.
Antes de evaluar un runtime, lee Requisitos de Harness para conocer los criterios de viabilidad y las brechas de capacidad que debes documentar. Sigue los requisitos mientras implementas el paquete del harness.
Un harness puede ser host-driven (impulsado por el anfitrión), donde el runtime se ejecuta en el proceso anfitrión y utiliza el sandbox de forma remota, o bridge-backed (respaldado por un puente), donde un pequeño puente se ejecuta dentro del sandbox porque el runtime necesita acceso local al sistema de archivos o al entorno de proceso del sandbox. Prefiere host-driven cuando el runtime lo soporte.
Harnesses de Primera Parte vs. de Terceros
- Paquetes de terceros: Cualquier runtime puede publicar un paquete de harness externo.
- Paquetes
@ai-sdk/harness-<nombre>de primera parte: Primero crea un issue para discutir si el runtime pertenece a este repositorio.
Ejemplo de Referencia
Consulta https://github.com/vercel/ai/pull/16255/changes para ver un ejemplo completo de cómo añadir un nuevo harness.
Arquitectura del Harness
El AI SDK utiliza una arquitectura de harness en capas que sigue el patrón de adaptador:
- Especificación del harness (
@ai-sdk/harness): Define interfaces comoHarnessV1yHarnessV1Session - Utilidades (
@ai-sdk/harness/utils): Código compartido para implementar harnesses - Implementaciones del harness (
@ai-sdk/harness-<nombre>): Adaptadores concretos para harnesses - Agente del harness (
@ai-sdk/harness/agent): La API de alto nivelHarnessAgentorientada al usuario final
Guía Paso a Paso
1. Crear la Estructura del Paquete
Crea packages/harness-<nombre> con esta estructura base:
packages/harness-<nombre>/
├── src/
│ ├── index.ts
│ ├── <nombre>-harness.ts
│ ├── <nombre>-harness.test.ts
│ └── <nombre>-auth.ts # si el runtime necesita resolución de autenticación
├── package.json
├── tsconfig.json
├── tsconfig.build.json
├── tsdown.config.ts
├── turbo.json
├── vitest.node.config.js
└── README.md
Si el runtime debe ejecutarse dentro del sandbox, añade también los archivos del puente:
src/
├── <nombre>-bridge-protocol.ts
├── <nombre>-bridge-protocol.test.ts
└── bridge/
├── index.ts
├── package.json
└── pnpm-lock.yaml
Añade un CHANGELOG.md que contenga solo el encabezado del paquete (# @ai-sdk/harness-<nombre>). Todos los paquetes deben tener uno.
2. Configurar package.json
Utiliza los paquetes de harness existentes como fuente de verdad para scripts, exportaciones, metadatos del repositorio y ajustes de publicación.
Requisitos básicos del paquete:
"name": "@ai-sdk/harness-<nombre>""type": "module""version": "0.0.0"(punto de partida para paquetes nuevos)"license": "Apache-2.0""sideEffects": false- dependencia de
@ai-sdk/harnessmedianteworkspace:* - dependencia de
@ai-sdk/provider-utilsmedianteworkspace:*cuando se utilicen utilidades de sandbox/autenticación/esquema - dependencias del SDK/CLI del runtime requeridas por el harness
- dependencias de desarrollo que coincidan con los paquetes de harness existentes
"engines": { "node": ">=22" }
Para paquetes con puente, añade cualquier paso de copia de activos del puente necesario para los archivos en src/bridge/.
Reglas de dependencias del puente (harnesses bridge-backed):
- Las dependencias de runtime del puente residen en
src/bridge/package.json(instaladas dentro del sandbox al iniciar), no en elpackage.jsonprincipal. Después de modificarlas, regenerasrc/bridge/pnpm-lock.yamlconpnpm --dir packages/harness-<nombre>/src/bridge install --lockfile-only --ignore-workspace(ejecutable desde la raíz del repositorio). - Para cada importación de terceros en
src/bridge/, añade la dependencia asrc/bridge/package.jsonpara que se instale en el sandbox.tsdownexternaliza automáticamente las dependencias, dependencias entre pares y dependencias opcionales declaradas por el paquete principal; añade las dependencias exclusivas del puente que no estén declaradas allí adeps.neverBundleentsdown.config.ts. Una dependencia faltante o exclusión requerida puede manifestarse solo en tiempo de ejecución del sandbox como un error de resolución de módulo. - Incluye paquetes que el runtime importa perezosamente — por ejemplo, SDKs de proveedores (
@anthropic-ai/sdk,openai) resueltos a partir del ID del modelo en tiempo de ejecución — ensrc/bridge/package.jsonaunque nada los importe directamente. No necesitan una entrada enneverBundlea menos que el código fuente del puente los importe. Estos fallan solo cuando se utiliza realmente un modelo de ese proveedor. - Haz coincidir las versiones de dependencias compartidas (transporte, esquema, herramientas, SDKs de runtime) con las que usan actualmente los otros paquetes de harness — copia de un paquete hermano en lugar de elegir tus propias versiones. Las versiones obsoletas se desvían de los parches de seguridad y pueden desincronizarse del runtime del puente compartido; verifica las versiones actuales en el momento de la creación.
3. Crear Configuraciones de TypeScript, Compilación y Pruebas
Copia los archivos de configuración del paquete de harness existente más cercano y ajusta las rutas/nombres de paquetes:
tsconfig.jsontsconfig.build.jsontsdown.config.tsturbo.jsonvitest.node.config.js
Los paquetes de harness actualmente usan solo pruebas de Node a menos que la implementación tenga una razón específica para añadir otro runtime.
4. Implementar el Adaptador del Harness
Exporta una fábrica desde <nombre>-harness.ts y re-expórtala desde src/index.ts.
Usa el documento de arquitectura para los detalles del contrato. Al momento de la implementación, verifica:
- devuelve un
HarnessV1conspecificationVersion: 'harness-v1'; - usa un
harnessIdestable en kebab-case; - expone las herramientas integradas nativas del adaptador a través de
builtinTools; - mantén la construcción síncrona y sin efectos secundarios;
- usa
startOpts.sandboxSessionystartOpts.sessionWorkDir; nunca crees un sandbox separado; - lanza
HarnessCapabilityUnsupportedErrordesde el método que necesita una capacidad del runtime no soportada; - no codifiques un modelo predeterminado a menos que el runtime técnicamente lo requiera — algunos SDK subyacentes no tienen un valor predeterminado propio. De lo contrario, pasa el modelo solo cuando el consumidor haya configurado uno y deja intacto el valor predeterminado del SDK original; mantén el
modelIdde la sesión coherente con lo que realmente se envía (no informes un modelo que el puente haya sobrescrito silenciosamente); - maneja las
toolseinstructionsquedoPromptTurn/doContinueTurnpuedan recibir: si el runtime no aceptatoolspersonalizadas, lanzaHarnessCapabilityUnsupportedErrorpara que sea obvio en lugar de ignorarlas silenciosamente; si no tiene una entrada nativa deinstructions, prepéndelas al primer mensaje del usuario (la solución alternativa de Codex/Claude Code); - cita las rutas interpoladas (
workDir, directorio de estado del puente, …) al construir comandos de shell parasandbox.run/sandbox.spawn— pueden contener espacios.
Si el runtime necesita configuración dentro del sandbox, expone getBootstrap().
5. Implementar Aspectos Específicos del Runtime
Añade solo los aspectos que el runtime necesite:
- resolución de autenticación — para soporte de AI Gateway, usa la ayuda central
getAiGatewayAuthFromEnv()en lugar de leer directamente las variables de entorno. Esto asegura que tantoVERCEL_OIDC_TOKENcomoAI_GATEWAY_API_KEYse acepten como credenciales de Gateway. Cuando el runtime resuelve el proveedor por modelo, resuelve el proveedor a partir del ID del modelo y establece las variables de entorno de ese proveedor; si se enruta a través del gateway, ten en cuenta que las convenciones de URL base difieren según el proveedor (por ejemplo, un cliente de Anthropic añade/v1/messagesa una URL base raíz, un cliente de OpenAI añade a una base/v1); - atribución de cliente de AI Gateway — sigue la convención en los paquetes de harness existentes: define un valor de aplicación de cliente versionado, como
ai-sdk/harness-<nombre>/${VERSION}, y úsalo para las solicitudes de Gateway. Configura tanto los encabezadosUser-Agentcomox-client-appcuando el runtime/SDK subyacente los soporte; al menos uno de esos dos encabezados es obligatorio. Si el runtime no puede establecer encabezados arbitrarios directamente, usa el equivalente soportado por el runtime que produzca uno de esos encabezados (por ejemplo, una variable de entorno de aplicación de cliente del SDK); - traducción de esquemas de herramientas personalizadas — si conviertes el esquema JSON de las herramientas del anfitrión al formato de herramientas del runtime, convierte recursivamente (objetos anidados,
itemsde arrays, enumeraciones, descripciones); una conversión plana solo a nivel superior descarta silenciosamente la guía estructurada del modelo. Pasar el esquema JSON directamente, si el runtime lo acepta, evita el problema; - materialización de habilidades o archivos de descubrimiento;
- traducción de protocolo nativo a flujo/control del harness;
- esquema de estado del ciclo de vida;
- protocolo del puente y diagnósticos.
Ciertas convenciones estructurales para los adaptadores de harness se están aplicando a través del CLI konsistent.
Ejecuta pnpm konsistent una vez que hayas terminado para verificarlas. Corrige cualquier infracción marcada antes de continuar.
6. Escribir Pruebas
Añade pruebas de Node enfocadas para:
- metadatos y configuración de la fábrica;
- resolución de autenticación;
- uso del sandbox y ubicación de rutas;
- operaciones remotas host-driven o comportamiento del protocolo del puente;
- traducción de eventos de solicitud/control;
- comportamiento de reanudación de sesión frente a continuación de turno;
- errores de capacidad no soportada;
- materialización de habilidades, si se soporta.
Usa sesiones de sandbox simuladas y límites de puente/runtime cuando sea posible. No requieras credenciales de proveedor en vivo en las pruebas unitarias.
getBootstrap() lee los activos del puente compilados (por ejemplo, dist/bridge/index.mjs), que no existen cuando las pruebas se ejecutan contra src, por lo que una prueba que lo llame encontrará ENOENT. Simula readFile de node:fs/promises para las rutas de activos del puente (consulta las pruebas del harness de Codex/OpenCode para ver el patrón).
7. Añadir README
Mantén el README breve:
- propósito del paquete;
- comando de configuración;
- uso mínimo de
HarnessAgent; - capacidades del sandbox requeridas, como puertos para runtimes bridge-backed;
- configuración de autenticación notable.
Enlaza a la documentación principal del harness para conceptos más amplios.
8. Añadir Ejemplos
Añade ejemplos relevantes para el nuevo harness.
- Añade ejemplos de funciones/API requeridos en
examples/ai-functions/src/harness-agenty ejemplos interactivos enexamples/harness-e2e-next.
9. Añadir Documentación
Crea documentación en content/providers/02-ai-sdk-harnesses/<siguiente-número>-<nombre>.mdx.
Incluye:
- Instrucciones de configuración
- Capacidades del sandbox requeridas
- Configuración de autenticación
- Opciones específicas del harness
- Ejemplos de uso
- Limitaciones conocidas
Actualiza content/docs/03-ai-sdk-harnesses/05-harness-adapters.mdx para listar el nuevo harness cuando esté listo para ser público.
10. Actualizar Referencias y Validar
Ejecuta desde la raíz del espacio de trabajo:
pnpm konsistent
pnpm update-references
pnpm --filter @ai-sdk/harness-<nombre> build
pnpm --filter @ai-sdk/harness-<nombre> test
pnpm type-check:full
Añade un changeset con pnpm changeset. Para el primer lanzamiento de un paquete de harness completamente nuevo, usa major (no el habitual patch), coincidiendo con los otros paquetes de harness.
Ejecuta los ejemplos de harness relevantes contra un sandbox en vivo temprano — no te bases solo en pruebas unitarias y type-check. Las limitaciones de la API del runtime (por ejemplo, rechazos inesperados de opciones de configuración, los nombres exactos de eventos de streaming que emite el runtime, el formato de la URL base de Gateway) solo se manifiestan cuando el puente realmente impulsa el runtime, y es mucho más barato encontrarlos antes de que se construyan los documentos/ejemplos encima.
Lista de Verificación
- Estructura del paquete creada en
packages/harness-<nombre> -
package.jsonconfigurado con las dependencias correctas - Configuraciones de TypeScript configuradas (
tsconfig.json,tsconfig.build.json) - Configuración de compilación (
tsdown.config.ts) - Configuración de pruebas (
vitest.node.config.js) - Implementación del adaptador del harness completa
- Ubicación del runtime manejada sin crear un sandbox oculto
- Activos del puente copiados durante la compilación, si es bridge-backed
- Resolución de autenticación implementada, si es necesario
- Las solicitudes de AI Gateway incluyen atribución de cliente
User-Agenty/ox-client-app - Infraestructura del harness, habilidades, código del puente y secretos mantenidos fuera de
sessionWorkDir - Reanudación de sesión y continuación de turno probados
- Pruebas unitarias escritas y pasando
- README.md escrito
-
CHANGELOG.mdañadido (encabezado del paquete; requerido porkonsistent) - Changeset añadido (
majorpara un primer lanzamiento) - Ejemplos añadidos
- Documentación añadida en
content/providers/02-ai-sdk-harnesses/ - Lista de adaptadores de harness actualizada, si es pública
- Validado contra un sandbox en vivo (no solo pruebas unitarias / type-check)
-
pnpm update-referencesejecutado - Compilación del paquete pasando
- Pruebas del paquete pasando
- Verificación de tipos pasando (
pnpm type-check:fulldesde la raíz) - Ejemplos relevantes ejecutados con éxito
Documentación Relacionada
- Arquitectura de Abstracción del Harness
- README de
@ai-sdk/harness - Paquetes de harness existentes con ubicación de runtime similar