Toda chamada de modelo falhando depois da v0.22.6? Confira primeiro o caminho do SSL_CERT_FILE

A rede da sua empresa passa por um proxy que abre o HTTPS e inspeciona. Você resolveu isso meses atrás: exportou a raiz corporativa como bundle, export SSL_CERT_FILE=/etc/corp/ca-bundle.pem, e curl, pip e git se comportam bem. Aí você atualiza o Hermes, manda uma mensagem e vê ela travar: certificate is not trusted no log, três retries e um “Provider temporarily unavailable” seco.
Sua rede não está quebrada e as configurações de proxy não estão erradas. Desde a v0.22.6, o cliente de modelos resolve a confiança de certificados por um caminho novo, e o bundle indicado em SSL_CERT_FILE não veio junto.
Primeiro, confirme que é este problema
Os sintomas são bem característicos:
- Todos os provider falham, não só um, e trocar de modelo não muda nada.
- A cadeia de erro é
httpcore.ConnectError→httpx.ConnectError→openai.APIConnectionError: Connection error., com"[host] certificate is not trusted"no meio. curlouopenssl s_clientchegam no mesmo host sem problema, porque eles leemSSL_CERT_FILE.- Voltar a mesma máquina para a v0.22.5 restaura o funcionamento normal.
Quatro de quatro significa resolução de confiança de certificados, não política de rede.
O que mudou no código
Em agent/ssl_verify.py, adicionado na v0.22.6, resolve_httpx_verify() responde contra qual confiança este cliente HTTP deve verificar. A ordem é: verificação explicitamente desligada → um bundle ssl_ca_cert explícito → o store da plataforma. O problema fica perto desse último passo:
if os.environ.get("SSL_CERT_FILE") or os.environ.get("SSL_CERT_DIR"):
return _shared_context(None)
_shared_context(None) quer dizer “só o store da plataforma, sem CA bundle extra”. Então exportar SSL_CERT_FILE te joga num ramo que ignora a variável.
O docstring do próprio módulo declara o contrato oposto: um bundle exportado em SSL_CERT_FILE é confiado além do store da plataforma, e só configuração explícita por provider (ssl_ca_cert, ssl_verify: false) substitui essa confiança. platform_ssl_context(), no mesmo arquivo, implementa exatamente essa união. O ramo da variável de ambiente e o resto do módulo discordam.
Por que o Linux parecia bem é a parte interessante: o backend OpenSSL do truststore chama set_default_verify_paths(), e o OpenSSL lê SSL_CERT_FILE sozinho, então a confiança chegava por acidente. O macOS verifica via SecTrustSetAnchorCertificates e o Windows via CryptoAPI; nenhum dos dois consulta o ambiente do OpenSSL, então os dois falham de vez. É por isso que a mesma configuração corporativa quebra o Mac de um colega enquanto sua máquina Linux segue funcionando.
Três formas de contornar, em ordem de preferência
1. Instale a raiz no store de confiança do sistema operacional (o que os docs recomendam)
A documentação de segurança é explícita: instale a raiz de um proxy TLS corporativo pelo procedimento de confiança do sistema operacional da sua organização. Feito isso, SSL_CERT_FILE deixa de importar para chamadas de provider. No macOS, marque o certificado como sempre confiável no Acesso às Chaves; no Windows, importe em Autoridades de Certificação Raiz Confiáveis via certlm.msc; no Debian/Ubuntu, coloque o pem em /usr/local/share/ca-certificates/ e rode update-ca-certificates. Opção mais limpa, sobrevive a upgrades, exige direitos de admin.
2. Aponte o provider para o bundle explicitamente
Se você não pode mexer no store do sistema, defina o CA bundle na entrada do provider:
providers:
deepseek:
api: https://api.deepseek.com
key_env: DEEPSEEK_API_KEY
ssl_ca_cert: ${env:SSL_CERT_FILE}
ssl_ca_cert substitui a confiança da plataforma para o chat, os metadados de modelo e as sondas de catálogo desse endpoint. Ele só conserta este provider, o que normalmente é o que você quer; um caminho errado registra um aviso e cai de volta na confiança da plataforma em vez de falhar em silêncio.
3. Desligue a verificação (só para desenvolvimento local)
ssl_verify: false faz as chamadas funcionarem na hora e te abre para qualquer man-in-the-middle no caminho — atrás de um proxy corporativo que inspeciona, isso significa confiar no proxy inteiro. Os docs chamam de inseguro para redes não confiáveis e avisam para não usar como correção permanente de uma raiz ausente. Use para diagnosticar, não para produção.
Como isso será corrigido
O PR de correção (#148253) muda esse ramo para devolver platform_ssl_context() em vez de _shared_context(None), restaura a união documentada e explica por que o Linux parecia funcionar. Na altura da release v0.22.7 ele continua aberto, então a build estável que você instala hoje se comporta como antes. Se você está esperando, a checagem é simples: uma release depois, veja se esse ramo em agent/ssl_verify.py devolve platform_ssl_context().
Um hábito que vale manter
Problemas de certificado se disfarçam de “a rede caiu” ou “o provider está fora do ar”, porque o sintoma na superfície é um erro de conexão. Da próxima vez que todos os provider falharem de uma vez, faça primeiro um teste em camadas: curl --cacert "$SSL_CERT_FILE" https://<host>. Se isso funcionar, a falha está na resolução de confiança da aplicação, não na rede — e você acabou de economizar meia hora de capturas de pacote.
Para continuar lendo: modelos locais e certificados autoassinados, criptografar segredos localmente, o que mais tem na janela da v0.22.7, instalar e atualizar.