Pular para o conteúdo principal

Documentação oficial desta página · v0.20.6

Resolução do runtime de provedores

O Hermes tem um resolvedor de runtime de provedores compartilhado, usado em:

  • CLI
  • gateway
  • tarefas de cron
  • ACP
  • chamadas a modelos auxiliares

Implementação principal:

  • hermes_cli/runtime_provider.py — resolução de credenciais e resolução de runtime para endpoints personalizados
  • hermes_cli/auth.py — registro de provedores, resolve_provider()
  • hermes_cli/model_switch.py — pipeline compartilhado da troca /model (CLI + gateway)
  • agent/auxiliary_client.py — roteamento de modelos auxiliares
  • providers/ — ABC + pontos de entrada do registro (ProviderProfile, register_provider, get_provider_profile, list_providers)
  • plugins/model-providers/<name>/ — plugins por provedor (embutidos) que declaram api_mode, base_url, env_vars, fallback_models e se registram no registro no primeiro acesso. Plugins do usuário em $HERMES_HOME/plugins/model-providers/<name>/ substituem os embutidos de mesmo nome.

O get_provider_profile() em providers/ devolve um ProviderProfile para um id de provedor. O runtime_provider.py chama isso na hora da resolução para obter o base_url canônico, a lista de prioridade de env_vars, o api_mode e os fallback_models sem precisar duplicar esses dados em vários arquivos. Basta adicionar um plugin novo em plugins/model-providers/<seu-provedor>/ (ou $HERMES_HOME/plugins/model-providers/<seu-provedor>/) que chame register_provider() para o runtime_provider.py reconhecê-lo — não é preciso nenhum desvio dentro do próprio resolvedor.

Se você quer adicionar um provedor de inferência de primeira classe, leia Adicionar Provedores e o guia de Plugin de Modelo junto com esta página.

Precedência da resolução​

Em alto nível, a resolução de provedor segue esta ordem:

  1. pedido explícito da CLI/runtime
  2. configuração de modelo/provedor no config.yaml
  3. variáveis de ambiente
  4. padrões específicos do provedor ou resolução automática

Essa ordem importa porque o Hermes trata a escolha salva de modelo/provedor como a fonte da verdade em execuções normais. Isso evita que um export velho no shell sobreponha em silêncio o endpoint que o usuário selecionou por último no hermes model.

Provedores​

As famílias de provedores atuais incluem (veja plugins/model-providers/ para o conjunto embutido completo):

  • AI Gateway (Vercel)
  • OpenRouter
  • Nous Portal
  • OpenAI Codex
  • Copilot / Copilot ACP
  • Anthropic (nativo)
  • Google / Gemini (gemini)
  • Alibaba / DashScope (alibaba, alibaba-coding-plan)
  • DeepSeek
  • Z.AI
  • Kimi / Moonshot (kimi-coding, kimi-coding-cn)
  • MiniMax (minimax, minimax-cn, minimax-oauth)
  • Kilo Code
  • Hugging Face
  • OpenCode Zen / OpenCode Go
  • AWS Bedrock
  • Azure Foundry
  • NVIDIA NIM
  • xAI (Grok)
  • Arcee
  • GMI Cloud
  • StepFun
  • Qwen OAuth
  • Xiaomi
  • Ollama Cloud
  • LM Studio
  • Tencent TokenHub
  • Custom (provider: custom) — provedor de primeira classe para qualquer endpoint compatível com OpenAI
  • Provedores personalizados nomeados (dicionário providers: no config.yaml; a lista antiga custom_providers ainda é lida por compatibilidade)

O que a resolução de runtime devolve​

O resolvedor de runtime devolve dados como:

  • provider
  • api_mode
  • base_url
  • api_key
  • source
  • metadados específicos do provedor, como informação de expiração/renovação

Por que isso importa​

Esse resolvedor é a principal razão de o Hermes conseguir compartilhar a lógica de autenticação e runtime entre:

  • hermes chat
  • tratamento de mensagens no gateway
  • tarefas de cron rodando em sessões novas
  • sessões ACP no editor
  • tarefas de modelo auxiliar

AI Gateway​

Defina AI_GATEWAY_API_KEY em ~/.hermes/.env e rode com --provider ai-gateway. O Hermes busca os modelos disponíveis no endpoint /models do gateway, filtrando por modelos de linguagem com suporte a uso de ferramentas.

OpenRouter, AI Gateway e base URLs personalizadas compatíveis com OpenAI​

O Hermes tem lógica para evitar vazar a chave de API errada para um endpoint personalizado quando existem várias chaves de provedor (por exemplo, OPENROUTER_API_KEY, AI_GATEWAY_API_KEY e OPENAI_API_KEY).

A chave de API de cada provedor fica restrita à sua própria base URL:

  • OPENROUTER_API_KEY só é enviada para endpoints em openrouter.ai
  • AI_GATEWAY_API_KEY só é enviada para endpoints em ai-gateway.vercel.sh
  • OPENAI_API_KEY é usada para endpoints personalizados e como reserva

O Hermes também distingue entre:

  • um endpoint personalizado de verdade, escolhido pelo usuário
  • o caminho de reserva pelo OpenRouter, usado quando não há endpoint personalizado configurado

Essa distinção é especialmente importante para:

  • servidores de modelo locais
  • APIs compatíveis com OpenAI que não são OpenRouter nem AI Gateway
  • trocar de provedor sem refazer a configuração
  • endpoints personalizados salvos na configuração, que precisam continuar funcionando mesmo quando OPENAI_BASE_URL não está exportada no shell atual

Caminho nativo da Anthropic​

A Anthropic não é mais só "via OpenRouter".

Quando a resolução de provedor escolhe anthropic, o Hermes usa:

  • api_mode = anthropic_messages
  • a Messages API nativa da Anthropic
  • agent/anthropic_adapter.py para a tradução

A resolução de credenciais para a Anthropic nativa agora prefere credenciais renováveis do Claude Code em vez de tokens copiados para variáveis de ambiente, quando ambos existem. Na prática:

  • arquivos de credencial do Claude Code são a fonte preferida quando incluem autenticação renovável
  • valores manuais de ANTHROPIC_TOKEN / CLAUDE_CODE_OAUTH_TOKEN continuam funcionando como sobreposição explícita
  • o Hermes faz a renovação preventiva das credenciais da Anthropic antes de chamar a Messages API nativa
  • o Hermes ainda tenta de novo uma vez após um 401, depois de reconstruir o cliente da Anthropic, como caminho de reserva

Caminho do OpenAI Codex​

O Codex usa um caminho separado, com a Responses API:

  • api_mode = codex_responses
  • resolução de credenciais dedicada e suporte a armazenamento de autenticação

Roteamento de modelos auxiliares​

Tarefas auxiliares como:

  • visão
  • resumo de extração web
  • resumos de compressão de contexto
  • operações do hub de skills
  • operações auxiliares de MCP
  • descargas de memória

podem usar roteamento próprio de provedor/modelo em vez do modelo conversacional principal.

Quando uma tarefa auxiliar está configurada com o provedor main, o Hermes resolve isso pelo mesmo caminho de runtime compartilhado do chat normal. Na prática:

  • endpoints personalizados vindos de variáveis de ambiente continuam funcionando
  • endpoints personalizados salvos pelo hermes model / config.yaml também funcionam
  • o roteamento auxiliar consegue distinguir entre um endpoint personalizado salvo de verdade e a reserva do OpenRouter

Modelos de reserva​

O Hermes suporta uma cadeia configurada de provedores de reserva — uma lista de entradas (provider, model) tentadas em ordem quando o modelo principal encontra erros. O dicionário antigo fallback_model, com um único par, ainda é aceito por compatibilidade (e é migrado na primeira gravação).

Como funciona por dentro​

  1. Armazenamento: AIAgent.__init__ guarda o dicionário fallback_model e define _fallback_activated = False.

  2. Pontos de disparo: _try_activate_fallback() é chamado de três lugares no laço principal de retentativas em run_agent.py:

    • depois do máximo de retentativas em respostas de API inválidas (choices nulo, conteúdo ausente)
    • em erros de cliente que não permitem retentativa (HTTP 401, 403, 404)
    • depois do máximo de retentativas em erros transitórios (HTTP 429, 500, 502, 503)
  3. Fluxo de ativação (_try_activate_fallback):

    • devolve False na hora se já estiver ativado ou não estiver configurado
    • chama resolve_provider_client() do auxiliary_client.py para montar um cliente novo com a autenticação correta
    • determina o api_mode: codex_responses para openai-codex, anthropic_messages para anthropic, chat_completions para todo o resto
    • troca no lugar: self.model, self.provider, self.base_url, self.api_mode, self.client, self._client_kwargs
    • para a reserva da anthropic: monta um cliente nativo da Anthropic em vez de um compatível com OpenAI
    • reavalia o cache de prompt (habilitado para modelos Claude no OpenRouter)
    • define _fallback_activated = True — impede que dispare de novo
    • zera a contagem de retentativas e segue o laço
  4. Fluxo de configuração:

    • CLI: lê a cadeia de reserva por hermes_cli/fallback_config.get_fallback_chain() → passa para AIAgent(fallback_model=...)
    • Gateway: gateway/run.py._load_fallback_model() lê o config.yaml → passa para o AIAgent
    • Validação: as chaves provider e model precisam estar preenchidas, senão a reserva fica desativada

O que NÃO suporta reserva​

  • Delegação a subagentes (tools/delegate_tool.py): subagentes herdam o provedor do pai, mas não a configuração de reserva
  • Tarefas auxiliares: usam a própria cadeia independente de detecção automática de provedor (veja "Roteamento de modelos auxiliares" acima)

Tarefas de cron suportam reserva: run_job() lê fallback_providers (ou o antigo fallback_model) do config.yaml e passa para AIAgent(fallback_model=...), no mesmo padrão do _load_fallback_model() do gateway. Veja Cron por Dentro.

Cobertura de testes​

O comportamento de reserva é exercitado em várias suítes:

  • tests/run_agent/test_fallback_credential_isolation.py — isolamento de credenciais entre o primário e a reserva
  • tests/hermes_cli/test_fallback_cmd.py — o comando /fallback da CLI
  • tests/gateway/test_fallback_eviction.py — remoção de provedores com falha no gateway