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:
- Especificação do harness (
@ai-sdk/harness): Define interfaces comoHarnessV1eHarnessV1Session - Utilitários (
@ai-sdk/harness/utils): Código compartilhado para implementar harnesses - Implementações de harness (
@ai-sdk/harness-<nome>): Adaptadores concretos para harnesses - Agente harness (
@ai-sdk/harness/agent): A APIHarnessAgentde 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/harnessviaworkspace:* - dependência de
@ai-sdk/provider-utilsviaworkspace:*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, regeneresrc/bridge/pnpm-lock.yamlcompnpm --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 asrc/bridge/package.jsonpara 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á adeps.neverBundleemtsdown.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 — emsrc/bridge/package.jsonmesmo que nada os importe diretamente. Eles não precisam de uma entradaneverBundlea 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.jsontsconfig.build.jsontsdown.config.tsturbo.jsonvitest.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
HarnessV1comspecificationVersion: 'harness-v1'; - use um
harnessIdkebab-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.sandboxSessionestartOpts.sessionWorkDir; nunca crie um sandbox separado; - lance
HarnessCapabilityUnsupportedErrora 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
modelIdda sessão consistente com o que é realmente enviado (não relate um modelo que o bridge sobrescreveu silenciosamente); - lide com
toolseinstructionsquedoPromptTurn/doContinueTurnpodem receber: se o runtime não aceitartoolspersonalizadas, lanceHarnessCapabilityUnsupportedErrorpara que seja óbvio em vez de ignorado silenciosamente; se não tiver entrada nativa deinstructions, 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 parasandbox.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 tantoVERCEL_OIDC_TOKENquantoAI_GATEWAY_API_KEYsejam 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/messagesa 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çalhosUser-Agentex-client-appquando 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,
itemsde 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-agente exemplos interativos emexamples/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.jsonconfigurado 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-Agente/oux-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.mdadicionado (cabeçalho do pacote; exigido pelokonsistent) - Changeset adicionado (
majorpara 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-referencesexecutado - Build do pacote passando
- Testes do pacote passando
- Verificação de tipos passando (
pnpm type-check:fulla partir da raiz) - Exemplos relevantes executados com sucesso
Documentação Relacionada
- Arquitetura de Abstração Harness
- README do
@ai-sdk/harness - Pacotes harness existentes com posicionamento de runtime semelhante