clanker25/ai

Guia para adicionar novos pacotes de harness do AI SDK. Use ao criar um novo pacote @ai-sdk/harness-<nome> que adapta um runtime de agente de codificação ao HarnessV1.

O que é ai?

Este guia detalha o processo de criação de um novo pacote de harness para o AI SDK, especificamente um pacote `@ai-sdk/harness-<nome>` que adapta um runtime de agente de codificação à interface `HarnessV1`. Ele é útil para desenvolvedores que precisam integrar novos runtimes de agentes (como Codex, Claude Code, etc.) ao ecossistema Vercel AI SDK, permitindo que esses runtimes sejam gerenciados através da API `HarnessAgent`. O documento cobre desde a estrutura do pacote, configuração de TypeScript e testes, até a implementação do adaptador harness, resolução de autenticação, suporte ao AI Gateway, e validação com um sandbox real. Ele também diferencia entre harnesses first-party (no repositório principal) e third-party (publicados externamente), e orienta sobre como lidar com runtimes host-driven (que executam fora do sandbox) versus bridge-backed (que exigem um bridge dentro do sandbox). O guia enfatiza a importância de testar cedo com um sandbox real para descobrir problemas de integração que não aparecem em testes unitários.

Funciona com✓Claude Code✓Codex CLI~Cursor✓OpenCode
npx skills add https://github.com/clanker25/ai/tree/HEAD/skills/add-harness-package

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Adicionando um Novo Pacote Harness

Este guia cobre a criação de um novo pacote @ai-sdk/harness-<nome> para um harness de agente.

Antes de avaliar um runtime, leia Requisitos do Harness para critérios de viabilidade e lacunas de capacidade a serem documentadas. Siga os requisitos ao implementar o pacote harness.

Um harness pode ser host-driven, onde o runtime roda no processo host e usa o sandbox remotamente, ou bridge-backed, onde um pequeno bridge roda dentro do sandbox porque o runtime precisa de acesso local ao sistema de arquivos ou ambiente de processo do sandbox. Prefira host-driven quando o runtime suportar.

Harnesses First-Party vs Third-Party

  • Pacotes third-party: Qualquer runtime pode publicar um pacote harness externo.
  • Pacotes first-party @ai-sdk/harness-<nome>: Crie uma issue primeiro para discutir se o runtime pertence a este repositório.

Exemplo de Referência

Veja https://github.com/vercel/ai/pull/16255/changes para um exemplo completo de adição de um novo harness.

Arquitetura do Harness

O AI SDK usa uma arquitetura de harness em camadas seguindo o padrão adapter:

  1. Especificação do harness (@ai-sdk/harness): Define interfaces como HarnessV1 e HarnessV1Session
  2. Utilitários (@ai-sdk/harness/utils): Código compartilhado para implementar harnesses
  3. Implementações de harness (@ai-sdk/harness-<nome>): Adaptadores concretos para harnesses
  4. Agente harness (@ai-sdk/harness/agent): A API HarnessAgent de alto nível voltada ao usuário

Guia Passo a Passo

1. Criar Estrutura do Pacote

Crie packages/harness-<nome> com esta estrutura básica:

packages/harness-<nome>/
├── src/
│   ├── index.ts
│   ├── <nome>-harness.ts
│   ├── <nome>-harness.test.ts
│   └── <nome>-auth.ts              # se o runtime precisar de resolução de autenticação
├── package.json
├── tsconfig.json
├── tsconfig.build.json
├── tsdown.config.ts
├── turbo.json
├── vitest.node.config.js
└── README.md

Se o runtime precisar executar dentro do sandbox, adicione também os arquivos bridge:

src/
├── <nome>-bridge-protocol.ts
├── <nome>-bridge-protocol.test.ts
└── bridge/
    ├── index.ts
    ├── package.json
    └── pnpm-lock.yaml

Adicione um CHANGELOG.md contendo apenas o cabeçalho do pacote (# @ai-sdk/harness-<nome>). Todo pacote é obrigado a ter um.

2. Configurar package.json

Use pacotes harness existentes como fonte da verdade para scripts, exports, metadados do repositório e configurações de publicação.

Itens básicos obrigatórios do pacote:

  • "name": "@ai-sdk/harness-<nome>"
  • "type": "module"
  • "version": "0.0.0" (ponto de partida para novos pacotes)
  • "license": "Apache-2.0"
  • "sideEffects": false
  • dependência de @ai-sdk/harness via workspace:*
  • dependência de @ai-sdk/provider-utils via workspace:* ao usar utilitários de sandbox/auth/schema
  • dependências do SDK/CLI do runtime exigidas pelo harness
  • devDependencies correspondendo aos pacotes harness existentes
  • "engines": { "node": ">=22" }

Para pacotes bridge, adicione qualquer etapa de cópia de assets bridge necessária para arquivos em src/bridge/.

Regras de dependência bridge (harnesses bridge-backed):

  • As dependências de runtime do bridge ficam em src/bridge/package.json (instaladas no sandbox na inicialização), não no package.json principal. Após alterá-las, regenere src/bridge/pnpm-lock.yaml com pnpm --dir packages/harness-<nome>/src/bridge install --lockfile-only --ignore-workspace (executável a partir da raiz do repositório).
  • Para cada importação de terceiros em src/bridge/, adicione a dependência a src/bridge/package.json para que seja instalada no sandbox. O tsdown externaliza automaticamente dependências, peerDependencies e optionalDependencies declaradas pelo pacote principal; adicione dependências exclusivas do bridge que não estão declaradas lá a deps.neverBundle em tsdown.config.ts. Uma dependência ausente ou exclusão necessária pode aparecer apenas em tempo de execução no sandbox como um erro de resolução de módulo.
  • Inclua pacotes que o runtime importa lazy — ex.: SDKs de provedor (@anthropic-ai/sdk, openai) resolvidos a partir do ID do modelo em tempo de execução — em src/bridge/package.json mesmo que nada os importe diretamente. Eles não precisam de uma entrada neverBundle a menos que o código fonte do bridge os importe. Estes falham apenas quando um modelo daquele provedor é realmente usado.
  • Corresponda as versões de dependências compartilhadas (transporte, schema, ferramentas, SDKs do runtime) ao que os outros pacotes harness estão usando atualmente — copie de um pacote irmão em vez de escolher suas próprias versões. Versões desatualizadas se afastam de patches de segurança e podem dessincronizar do runtime bridge compartilhado; verifique as versões atuais no momento da criação.

3. Criar Configurações TypeScript, Build e Teste

Copie os arquivos de configuração do pacote harness existente mais próximo e ajuste caminhos/nomes de pacote:

  • tsconfig.json
  • tsconfig.build.json
  • tsdown.config.ts
  • turbo.json
  • vitest.node.config.js

Pacotes harness atualmente usam apenas testes Node a menos que a implementação tenha um motivo específico para adicionar outro runtime.

4. Implementar o Adaptador Harness

Exporte uma fábrica de <nome>-harness.ts e re-exporte-a de src/index.ts.

Use o documento de arquitetura para detalhes do contrato. No momento da implementação, verifique:

  • retorne um HarnessV1 com specificationVersion: 'harness-v1';
  • use um harnessId kebab-case estável;
  • exponha ferramentas nativas do adaptador através de builtinTools;
  • mantenha a construção síncrona e livre de efeitos colaterais;
  • use startOpts.sandboxSession e startOpts.sessionWorkDir; nunca crie um sandbox separado;
  • lance HarnessCapabilityUnsupportedError a partir do método que precisar de uma capacidade de runtime não suportada;
  • não codifique um modelo padrão a menos que o runtime tecnicamente exija um — alguns SDKs subjacentes não têm um padrão próprio. Caso contrário, passe o modelo apenas quando o consumidor configurou um e deixe o padrão do SDK original intocado; mantenha o modelId da sessão consistente com o que é realmente enviado (não relate um modelo que o bridge sobrescreveu silenciosamente);
  • lide com tools e instructions que doPromptTurn/doContinueTurn podem receber: se o runtime não aceitar tools personalizadas, lance HarnessCapabilityUnsupportedError para que seja óbvio em vez de ignorado silenciosamente; se não tiver entrada nativa de instructions, anexe-as à primeira mensagem do usuário (solução alternativa do Codex/Claude Code);
  • coloque entre aspas caminhos interpolados (workDir, diretório de estado do bridge, …) ao construir comandos shell para sandbox.run/sandbox.spawn — eles podem conter espaços.

Se o runtime precisar de configuração dentro do sandbox, exponha getBootstrap().

5. Implementar Preocupações Específicas do Runtime

Adicione apenas as preocupações que o runtime precisa:

  • resolução de autenticação — para suporte ao AI Gateway, use o helper central getAiGatewayAuthFromEnv() em vez de ler env diretamente. Isso garante que tanto VERCEL_OIDC_TOKEN quanto AI_GATEWAY_API_KEY sejam aceitos como credencial do Gateway. Quando o runtime resolve o provedor por modelo, resolva o provedor a partir do ID do modelo e defina o env desse provedor; se roteando através do gateway, observe que as convenções de URL base diferem por provedor (ex.: um cliente Anthropic anexa /v1/messages a uma URL base raiz, um cliente OpenAI anexa a uma base /v1);
  • atribuição de cliente do AI Gateway — siga a convenção em pacotes harness existentes: defina um valor de aplicativo cliente versionado como ai-sdk/harness-<nome>/${VERSION} e use-o para requisições do Gateway. Configure ambos os cabeçalhos User-Agent e x-client-app quando o runtime/SDK subjacente suportar ambos; pelo menos um desses dois cabeçalhos é obrigatório. Se o runtime não puder definir cabeçalhos arbitrários diretamente, use o equivalente suportado pelo runtime que produza um desses cabeçalhos (ex.: uma variável de ambiente de aplicativo cliente SDK);
  • tradução de schema de ferramentas personalizadas — se você converter o JSON Schema das ferramentas do host para o formato de ferramentas do runtime, converta recursivamente (objetos aninhados, items de array, enums, descrições); uma conversão plana apenas no nível superior descarta silenciosamente a orientação estruturada do modelo. Passar o JSON Schema diretamente, se o runtime aceitá-lo, evita o problema;
  • materialização de skill ou arquivos de descoberta;
  • tradução de protocolo nativo para stream/controle do harness;
  • schema de estado do ciclo de vida;
  • protocolo bridge e diagnósticos.

Certas convenções estruturais para adaptadores harness estão sendo aplicadas via CLI konsistent. Execute pnpm konsistent quando terminar para verificar. Corrija quaisquer violações sinalizadas antes de prosseguir.

6. Escrever Testes

Adicione testes Node focados para:

  • metadados e configurações da fábrica;
  • resolução de autenticação;
  • uso do sandbox e posicionamento de caminhos;
  • operações remotas host-driven ou comportamento do protocolo bridge;
  • tradução de eventos de prompt/controle;
  • comportamento de retomada de sessão vs continuação de turno;
  • erros de capacidade não suportada;
  • materialização de skill, se suportado.

Use sessões sandbox simuladas e limites bridge/runtime quando possível. Não exija credenciais de provedor reais em testes unitários.

getBootstrap() lê os assets bridge compilados (ex.: dist/bridge/index.mjs), que não existem quando os testes rodam contra src, então um teste que o chama encontrará ENOENT. Simule readFile de node:fs/promises para os caminhos de assets bridge (veja os testes dos harnesses Codex/OpenCode para o padrão).

7. Adicionar README

Mantenha o README curto:

  • propósito do pacote;
  • comando de configuração;
  • uso mínimo de HarnessAgent;
  • capacidades de sandbox necessárias, como portas para runtimes bridge-backed;
  • configuração de autenticação notável.

Link para a documentação principal do harness para conceitos mais amplos.

8. Adicionar Exemplos

Adicione exemplos relevantes para o novo harness.

  • Adicione exemplos de API/função necessários em examples/ai-functions/src/harness-agent e exemplos interativos em examples/harness-e2e-next.

9. Adicionar Documentação

Crie documentação em content/providers/02-ai-sdk-harnesses/<próximo número>-<nome>.mdx.

Inclua:

  • Instruções de configuração
  • Capacidades de sandbox necessárias
  • Configuração de autenticação
  • Opções específicas do harness
  • Exemplos de uso
  • Limitações conhecidas

Atualize content/docs/03-ai-sdk-harnesses/05-harness-adapters.mdx para listar o novo harness quando estiver pronto para ser público.

10. Atualizar Referências e Validar

Execute a partir da raiz do workspace:

pnpm konsistent
pnpm update-references
pnpm --filter @ai-sdk/harness-<nome> build
pnpm --filter @ai-sdk/harness-<nome> test
pnpm type-check:full

Adicione um changeset com pnpm changeset. Para o primeiro lançamento de um pacote harness totalmente novo, use major (não o patch usual), correspondendo aos outros pacotes harness.

Execute exemplos de harness relevantes contra um sandbox real cedo — não confie apenas em testes unitários e type-check. Restrições da API do runtime (ex.: rejeições inesperadas de opções de configuração, os nomes exatos de eventos de stream que o runtime emite, formato da URL base do gateway) só aparecem quando o bridge realmente dirige o runtime, e são muito mais baratos de encontrar antes que a documentação/exemplos sejam construídos em cima.

Checklist

  • Estrutura do pacote criada em packages/harness-<nome>
  • package.json configurado com dependências corretas
  • Configurações TypeScript configuradas (tsconfig.json, tsconfig.build.json)
  • Configuração de build (tsdown.config.ts)
  • Configuração de teste (vitest.node.config.js)
  • Implementação do adaptador harness completa
  • Posicionamento do runtime tratado sem criar um sandbox oculto
  • Assets bridge copiados durante o build, se bridge-backed
  • Resolução de autenticação implementada, se necessário
  • Requisições AI Gateway incluem atribuição de cliente User-Agent e/ou x-client-app
  • Infraestrutura do harness, skills, código bridge e segredos mantidos fora de sessionWorkDir
  • Retomada de sessão e continuação de turno testados
  • Testes unitários escritos e passando
  • README.md escrito
  • CHANGELOG.md adicionado (cabeçalho do pacote; exigido pelo konsistent)
  • Changeset adicionado (major para um primeiro lançamento)
  • Exemplos adicionados
  • Documentação adicionada em content/providers/02-ai-sdk-harnesses/
  • Lista de adaptadores harness atualizada, se público
  • Validado contra um sandbox real (não apenas testes unitários / type-check)
  • pnpm update-references executado
  • Build do pacote passando
  • Testes do pacote passando
  • Verificação de tipos passando (pnpm type-check:full a partir da raiz)
  • Exemplos relevantes executados com sucesso

Documentação Relacionada

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

Habilidades Relacionadas