Como testar uma API compatível com OpenAI antes de conectar um agente
Teste chat, JSON estruturado, ida e volta de ferramentas, conclusão de SSE e erros de validação. Inclui script Python e testes locais de falhas.
Uma solicitação de chat bem-sucedida não prova que uma API compatível com OpenAI consegue executar seu agente. Teste as operações necessárias: saída estruturada, chamada de ferramenta com retorno ao modelo, conclusão do streaming e erros utilizáveis. Registre o endpoint e o modelo exato. A compatibilidade depende da rota, da solicitação e da resposta; não é um selo permanente do provedor.
Este guia oferece um pequeno verificador Python para Chat Completions. Ele envia no máximo seis solicitações, sem tentativas automáticas adicionais. A proposta é diferente de configurar OpenCode, Copilot ou n8n: primeiro verifique a rota que o cliente usará, depois configure e teste o próprio cliente. Passar aqui não certifica suporte à Responses API, capacidade sob carga ou todos os parâmetros da sua aplicação.
Baixe o verificador e entenda o alcance
Baixe check_api.py. São cinco verificações em seis solicitações, porque a interação com ferramenta exige a chamada inicial e outra contendo o resultado da ferramenta.
| Verificação | O que o script exige | O que um resultado positivo não prova |
|---|---|---|
| Chat básico | Resposta Chat Completions interpretável com a resposta curta solicitada | Ferramentas, streaming ou visão |
| Saída estruturada | Solicitação com schema estrito aceita; JSON aprovado pelo schema e pelos valores conhecidos | Todo o JSON Schema ou extração confiável de qualquer dado |
| Ida e volta de ferramenta | Tipo, nome, argumentos e ID corretos; resultado local reenviado; resposta final exata | Argumentos em streaming, ferramentas paralelas ou segurança de ferramentas remotas |
| Streaming | Tipo SSE, eventos interpretáveis, texto esperado, stop e [DONE] | Eventos de Responses ou reconexão |
| Erro de validação | Campo com tipo inválido retorna HTTP 400/422 e objeto de erro JSON | Todos os erros, política de repetição ou cobrança |
O conjunto de testes locais substitui as chamadas HTTP por respostas fixas: não abre conexões nem exige chave. Coloque-o ao lado de check_api.py, instale as dependências indicadas adiante e execute:
python test_check_api.py
python -O test_check_api.py
Em 7 de novembro de 2026, os nove casos produziram os resultados esperados nos dois modos: troca válida, stream truncado, resposta errada da ferramenta, tipo de ferramenta errado, valores de schema inválidos, resposta de chat errada, conteúdo nulo, erro de autenticação e limite de requisições. São testes reais do verificador local, não chamadas a um modelo hospedado. Aprovação do teste significa que o status observado corresponde ao esperado; respostas propositalmente defeituosas não devem todas retornar PASS. Não apresente um resultado simulado como resultado do provedor. Um teste real precisa de registro datado, rota, modelo e evidência de uso próprios.
Defina o endpoint e o limite de custo
Copie a raiz da API documentada pelo provedor. Neste script, uma raiz terminada em /v1 vira /v1/chat/completions. Não forneça o caminho completo de /chat/completions nem a página comercial do modelo. Confira se o modelo escolhido aceita esse protocolo antes de investigar credenciais.
No Ofox, consulte a documentação atual da API e a do modelo exato. Compatibilidade com OpenAI não significa suporte a todos os endpoints da OpenAI. Se o modelo exigir Responses para ferramentas, use o guia de migração para Responses (em inglês). Trocar apenas a URL deste verificador não adapta o formato das mensagens.
Escolha um modelo de baixo custo cujo uso esteja autorizado, confira o preço atual e configure um limite de gastos na conta, quando disponível. O script solicita um teto pequeno de tokens de saída e usa dados sintéticos, mas um parâmetro de tokens não garante um teto monetário. O provedor pode rejeitar ou interpretar o campo de outro modo; tokens de raciocínio também variam. Não escolha um modelo caro só porque o prompt é curto.
O campo padrão é max_completion_tokens. Se a documentação do modelo exigir max_tokens, use a opção correspondente. A rejeição do campo indica que a solicitação precisa seguir o contrato documentado; não demonstra incapacidade de gerar texto.
Instale e execute um teste controlado
Use uma versão atual do Python 3 com biblioteca TLS suportada. Crie um ambiente virtual para não alterar as dependências da aplicação:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install requests jsonschema
Defina LLM_API_KEY pelo método habitual de gerenciamento local de segredos. Não coloque a chave na linha de comando, em notebook público, captura de tela ou no script baixado. Prefira credencial temporária e limitada quando houver suporte.
python check_api.py \
--base-url https://api.example.com/v1 \
--model YOUR_EXACT_MODEL_ID \
--token-field max_completion_tokens \
--max-output 256 \
--out first-run.json
Substitua os exemplos api.example.com e YOUR_EXACT_MODEL_ID pelo endpoint documentado e pelo identificador real. O script exige HTTPS, exceto em um teste local de loopback explicitamente configurado. Redirecionamentos são desativados para evitar que um destino incorreto encaminhe silenciosamente a credencial Bearer. O script não sobrescreve um relatório existente: use outro nome em uma nova execução.
Há timeouts de conexão e leitura e uma verificação de prazo entre linhas SSE completas. Isso não constitui um limite rígido de duração total: um servidor que envie lentamente uma linha incompleta pode manter a leitura ativa. Execute este exemplo de forma interativa e interrompa chamadas travadas. Antes de usá-lo como monitor de produção sem supervisão, implemente um prazo real no nível do processo e limites de tamanho da resposta.
Interprete evidências, não uma pontuação
PASS significa que a resposta cumpriu aquela verificação. FAIL indica rejeição da solicitação ou descumprimento de uma condição esperada. UNKNOWN indica que um problema de transporte ou formato inesperado impediu uma conclusão confiável. Leia os detalhes e o status HTTP antes de decidir o que mudar.
Uma falha de rede não prova falta de suporte a ferramentas. Um 401 não é falha de JSON Schema. Um 429 na solicitação propositalmente inválida não prova validação de tipos: a rejeição pode ter ocorrido antes dessa etapa. Por isso, autenticação e limite de requisições não contam como aprovação do teste de erro de validação.
Não transforme os cinco resultados em “80% compatível”. Se o agente precisa de ferramentas, quatro verificações de outros recursos não compensam a falha nessa operação. Mantenha uma matriz dos recursos obrigatórios e opcionais da aplicação.
Uma execução real de seis solicitações no Ofox
Em 7 de novembro de 2026, executamos o script em https://api.ofox.ai/v1 com o modelo listado na conta openai/gpt-6-luna e max_completion_tokens: 256. Foram seis solicitações, incluindo a inválida, sem repetições. O resultado real em JSON registra tempos e uso retornado. Esta tradução mantém a evidência do teste original, sem alegar uma nova execução.
| Verificação | Resultado observado |
|---|---|
| Chat básico | PASS: resposta exigida e conclusão normal |
| Saída estruturada | PASS: schema, SKU e quantidade corresponderam |
| Ida e volta de ferramenta | PASS: segunda resposta igual a 17 |
| Streaming | PASS: texto, motivo de conclusão e [DONE] presentes |
| Parâmetro inválido | PASS: HTTP 400 com objeto de erro JSON |

A captura mostra um visualizador local do JSON salvo. Não é um painel do Ofox nem um teste adicional ao vivo.
Esses resultados descrevem aquele modelo, rota e conjunto de dados na data da execução. Não certificam todos os modelos, a aplicação interna de schema estrito, Responses, argumentos de ferramentas em streaming, fallback ou parâmetros adicionais do seu cliente. O 400 na solicitação inválida é o resultado esperado, não uma indisponibilidade do serviço.
Por que o resultado da ferramenta precisa voltar ao modelo
Uma resposta com tool_calls comprova apenas a primeira metade da interação. A aplicação deve validar a chamada, executar uma ferramenta permitida e devolver seu resultado com o ID correspondente. A segunda resposta do modelo precisa usar esse resultado corretamente.
O verificador expõe uma consulta local somente de leitura, lookup_stock. O SKU sintético 000102 retorna estoque fixo 17. Antes de devolver esse valor, o script confere tipo, nome, argumentos JSON e ID da chamada. Depois exige resposta final exatamente igual a 17. Nunca executa comandos shell nem funções arbitrárias sugeridas pelo modelo.
A tarefa restrita facilita o diagnóstico. Se a primeira chamada funciona e a segunda falha, examine o formato da mensagem de resultado e seu ID antes de trocar de modelo. Uma resposta 170 falha, mesmo contendo os caracteres “17”. As validações usam exceções explícitas e continuam ativas com a otimização do Python.
Em uma aplicação real, valide argumentos pelo schema, restrinja operações e trate permissões antes de executar. Uma chamada tecnicamente válida não autoriza envio de e-mail, pagamento ou alteração de banco de dados.
Separe JSON válido de tarefa concluída
O teste pede {"sku":"000102","quantity":3}. O schema exige SKU como string, quantidade inteira, os dois campos presentes e nenhuma propriedade extra. O script valida a estrutura e depois compara os valores com a resposta conhecida. Uma resposta correta não prova aplicação do modo estrito pelo servidor: o modelo poderia produzi-la mesmo que o gateway ignorasse o campo. Considere o resultado um comportamento observado, não uma prova da implementação interna.
Isso identifica falhas diferentes. O JSON pode ser válido e perder os zeros do SKU. O tipo pode estar correto e o valor errado. Um servidor pode aceitar o modo JSON comum e rejeitar o schema estrito. Preserve a solicitação exata; não remova strict silenciosamente para obter um resultado verde.
A documentação da OpenAI sobre saídas estruturadas (em inglês) distingue respostas estruturadas e chamadas de função. Siga o contrato do endpoint escolhido: copiar campos entre formatos de API não constitui um teste de compatibilidade.
Se sua tarefa for extração, prossiga com um documento de resposta conhecida e o fluxo de validação de texto para JSON (em inglês). Um schema pequeno e fixo é só uma verificação inicial.
Confira o encerramento do streaming
Receber algum texto não significa receber uma resposta completa. O script lê eventos SSE, reúne os trechos, registra o motivo da conclusão e exige o marcador [DONE] de Chat Completions. Um stream truncado falha mesmo se o texto parcial parecer plausível.
Essa é a regra do perfil escolhido, não de todas as APIs. Responses usa outros formatos de evento. O uso de tokens ao final do streaming também varia. O script não solicita stream_options e registra a ausência de uso sem tratá-la, isoladamente, como falha. Teste separadamente a opção documentada pelo provedor se faturamento ou monitoramento depender dela.
Depois de uma desconexão, não repita automaticamente um fluxo que possa ter executado uma ação externa. Primeiro confira se alguma ferramenta ou etapa posterior já rodou. O guia de desconexão de stream (em inglês) aborda um problema específico de cliente; uma repetição de rede genérica não garante retomada segura do agente.
Resolva a falha na camada responsável
| Observação | Primeiro ponto a investigar |
|---|---|
| Todas as solicitações retornam 401/403 | Credencial, acesso da conta e autorização no endpoint |
| 404 ou modelo não encontrado | URL, ID e disponibilidade na conta; veja diagnóstico de model-not-found (em inglês) |
| Chat funciona, schema estrito falha | Suporte documentado ao formato e subconjunto de schema aceito |
| Chamada inicial de ferramenta falha | Protocolo, capacidade do modelo e campos enviados |
| Envio do resultado da ferramenta falha | ID, histórico e formato da mensagem |
| Stream envia texto, mas não termina | Delimitação dos eventos SSE, buffering do proxy, encerramento da conexão e perfil incompatível |
| Credencial do n8n passa, execução falha | Endpoint realmente chamado; veja diagnóstico do n8n (em inglês) |
Depois que os requisitos passarem, configure o provedor personalizado no OpenCode (em inglês) ou outro cliente e repita uma tarefa pequena por ele. O cliente pode enviar campos não usados neste script. Guarde as duas evidências, sem presumir que o teste direto garante o comportamento da aplicação.
Antes de compartilhar relatórios, remova nomes de endpoints privados, IDs de requisição e dados específicos da conta, se houver. O exemplo contém apenas saídas sintéticas, modelo, tempos, status e uso; não grava a chave. Mantenha registros datados ao mudar versão ou rota. Eles são mais úteis que uma afirmação genérica de compatibilidade.


