Pular para o conteúdo principal

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

Microsoft Foundry

O provedor azure-foundry do Hermes Agent suporta o Microsoft Foundry (antigo Azure AI Foundry) e o Azure OpenAI. Um único recurso do Foundry pode hospedar modelos em dois formatos de protocolo diferentes:

  • Estilo OpenAI — POST /v1/chat/completions, em endpoints como https://<recurso>.openai.azure.com/openai/v1. Usado por GPT-4.x, GPT-5.x, Llama, Mistral e a maioria dos modelos de peso aberto.
  • Estilo Anthropic — POST /v1/messages, em endpoints como https://<recurso>.services.ai.azure.com/anthropic. Usado quando o Foundry serve modelos Claude pelo formato da API de mensagens da Anthropic.

O assistente de configuração sonda o seu endpoint e detecta sozinho qual transporte ele usa, quais implantações existem e o tamanho de contexto de cada modelo.

Pré-requisitos​

  • Um recurso do Microsoft Foundry ou do Azure OpenAI, com pelo menos uma implantação
  • A URL do endpoint da implantação
  • Ou uma chave de API (no Portal do Azure, em "Keys and Endpoint") ou o papel de RBAC Azure AI User no recurso, se você pretende usar o Microsoft Entra ID (o caminho sem chave, que a Microsoft recomenda). Alguns locatários mostram o papel como Foundry User, durante a renomeação em curso.

Começando​

hermes model
# → escolha "Azure Foundry"
# → informe a URL do endpoint
# → escolha a autenticação:
# 1. chave de API
# 2. Microsoft Entra ID (identidade gerenciada / de carga de trabalho / az login)
# → (Entra) o Hermes sonda o DefaultAzureCredential; dando certo, ele nunca pede chave
# → (chave) informe a sua chave de API
# O Hermes sonda o endpoint e detecta transporte e modelos
# → escolha um modelo da lista (ou digite o nome da implantação na mão)

O assistente vai:

  1. Farejar o caminho da URL — URLs terminadas em /anthropic são reconhecidas como rotas de Claude no Foundry.
  2. Sondar o GET <base>/models — se o endpoint devolver uma lista de modelos no formato da OpenAI, o Hermes muda para chat_completions e preenche o seletor com os identificadores devolvidos.
  3. Sondar o formato de mensagens da Anthropic — reserva para endpoints que não expõem /models, mas aceitam o formato da Anthropic.
  4. Cair na entrada manual — endpoints privados ou restritos, que recusam toda sondagem, ainda funcionam; você escolhe o modo de API e digita o nome da implantação.

O tamanho de contexto do modelo escolhido é resolvido pela cadeia de metadados padrão do Hermes (models.dev, metadados do provedor, e reservas fixas por família) e gravado no config.yaml, para o modelo dimensionar a própria janela corretamente.

A Microsoft recomenda autenticação sem chave, com o Microsoft Entra ID, para cargas de produção no Foundry. O Hermes suporta Entra ID nas duas superfícies de API:

  • Estilo OpenAI (api_mode: chat_completions ou codex_responses) — GPT-4/5, Llama, Mistral, DeepSeek e outros.
  • Estilo Anthropic (api_mode: anthropic_messages) — modelos Claude no Foundry.

O RBAC do Foundry é por recurso (o Azure AI User concede as duas superfícies; alguns locatários mostram Foundry User), e a Microsoft documenta o mesmo escopo de inferência (https://ai.azure.com/.default) para ambas. Por baixo:

  • O estilo OpenAI usa o contrato nativo de api_key= chamável do SDK Python da OpenAI — o SDK gera um JWT novo por requisição, sozinho.
  • O estilo Anthropic usa um httpx.Client com um gancho de evento de requisição, instalado por agent.azure_identity_adapter.build_bearer_http_client, porque o SDK da Anthropic não aceita auth_token chamável nativamente. O gancho reescreve Authorization: Bearer <jwt-novo> a cada requisição de saída. Mesmo RBAC, mesmo escopo — a única diferença é o contrato do SDK.

Por que usar o Entra ID?​

  • Nenhuma chave de API de vida longa para girar ou revogar.
  • Acesso conduzido por RBAC — conceda ou remova o Azure AI User no recurso, sem reescrever configuração.
  • Logs de acesso e auditoria segmentados por quem recebeu o papel, em vez de todos compartilharem uma chave estática.
  • Uma superfície de autenticação só, para máquinas virtuais do Azure, pods do AKS, App Service, Functions, Container Apps e o Foundry Agent Service, por identidade gerenciada.
  • Fluxos de identidade de carga de trabalho e de entidade de serviço, para pipelines de CI/CD.

Configuração inicial (do lado do Azure)​

  1. No Portal do Azure, abra o recurso do Foundry → Access control (IAM) → Add → Add role assignment.
  2. Escolha o papel Azure AI User (ou Foundry User, se o seu locatário já tem o nome novo).
  3. Atribua a:
    • A sua conta de usuário, para desenvolvimento local com az login.
    • Uma identidade gerenciada ou de carga de trabalho, para computação hospedada no Azure (recomendado em produção).
    • A identidade do agente hospedado no Foundry Agent Service, quando o Hermes roda dentro de um agente hospedado.
    • Uma entidade de serviço, para pipelines de CI/CD sem identidade de carga de trabalho.
  4. Espere uns 5 minutos, para o papel propagar.

Equivalente na CLI do Azure:

az role assignment create \
--assignee <id-do-cliente-da-identidade> \
--role "Azure AI User" \
--scope <id-do-recurso-foundry>

Configuração inicial (do lado do Hermes)​

hermes model
# → escolha "Azure Foundry"
# → informe a URL do endpoint
# → autenticação: 2 (Microsoft Entra ID)
# → (opcional) id de cliente da identidade gerenciada atribuída pelo usuário
# → (opcional) id do locatário do Azure
# → o Hermes sonda o DefaultAzureCredential() e informa qual credencial interna
# funcionou (AzureCliCredential, ManagedIdentityCredential etc.)

O assistente roda uma sondagem prévia limitada (10 segundos). Falhando, ele oferece "salvar assim mesmo, validar depois" — útil ao configurar numa máquina que ainda não tem credencial, mas terá em tempo de execução (preparando a configuração de uma implantação com identidade gerenciada, por exemplo).

O azure-identity é instalado sozinho no primeiro uso, pelo caminho de instalação sob demanda. Para instalar antes:

pip install azure-identity

O que vai para o config.yaml​

model:
provider: azure-foundry
base_url: https://meu-recurso.openai.azure.com/openai/v1
api_mode: chat_completions
auth_mode: entra_id
default: gpt-4o
context_length: 128000
entra:
scope: https://ai.azure.com/.default # só ao sobrescrever o padrão

O Hermes gerencia um único botão específico do Entra no config.yaml:

  • scope — o escopo do recurso OAuth. O padrão é o escopo de inferência documentado pela Microsoft (https://ai.azure.com/.default). Sobrescreva só se o seu recurso foi provisionado contra um público diferente do padrão.

Todo o resto (locatário, segredo de entidade de serviço, arquivo de token federado, autoridade de nuvem soberana, preferências de intermediário) é lido pelo azure-identity direto das variáveis de ambiente AZURE_* padrão — veja a ordem de resolução. Defina essas variáveis em ~/.hermes/.env ou no ambiente da sua implantação, exatamente como a referência do SDK da Microsoft descreve.

Nenhum segredo cai no ~/.hermes/.env no modo Entra — o azure-identity guarda os tokens em processo (e, onde há, no chaveiro do sistema ou em ~/.IdentityService).

Ordem de resolução das credenciais​

O DefaultAzureCredential do azure-identity percorre esta cadeia a cada pedido de token, parando na primeira credencial que devolve um:

  1. Credencial de ambiente — AZURE_TENANT_ID, AZURE_CLIENT_ID e AZURE_CLIENT_SECRET (ou AZURE_CLIENT_CERTIFICATE_PATH / AZURE_FEDERATED_TOKEN_FILE).
  2. Identidade de carga de trabalho — AZURE_FEDERATED_TOKEN_FILE (tokens federados do AKS, OIDC).
  3. Identidade gerenciada — o endpoint IMDS (169.254.169.254), em máquinas virtuais; IDENTITY_ENDPOINT no App Service, no Functions e no Container Apps. Agentes hospedados no Foundry Agent Service usam a identidade do próprio agente.
  4. Visual Studio Code — extensão de conta do Azure.
  5. CLI do Azure — sessão de az login.
  6. Azure Developer CLI — azd auth login.
  7. Azure PowerShell — Connect-AzAccount.
  8. Intermediário (só no Windows e no WSL) — Web Account Manager.

A credencial de navegador interativo fica excluída por padrão, para execuções sem supervisão; use a CLI do Azure, a Azure Developer CLI, identidade gerenciada, identidade de carga de trabalho ou entidade de serviço.

Padrões de implantação​

Desenvolvimento local:

az login
hermes model # escolha Azure Foundry → Entra ID
hermes # usa o token do seu az login

Máquina virtual, Functions, App Service ou Container Apps (identidade gerenciada atribuída pelo sistema):

  1. Habilite a identidade atribuída pelo sistema no recurso de computação.
  2. Conceda a ela o Azure AI User (ou Foundry User) no recurso do Foundry.
  3. Defina model.auth_mode: entra_id no config.yaml — sem variáveis de ambiente.

Máquina virtual, Functions, App Service ou Container Apps (identidade atribuída pelo usuário):

  • Defina o AZURE_CLIENT_ID com o identificador de cliente daquela identidade, para o DefaultAzureCredential escolher a certa.

Agente hospedado no Foundry Agent Service:

  • Crie o agente e conceda à identidade dele o Azure AI User (ou Foundry User) no recurso. O Hermes usa o ManagedIdentityCredential de dentro do agente hospedado; a atribuição de papel pertence à identidade do agente, não só ao projeto pai nem ao seu usuário.

Identidade de carga de trabalho no AKS (substitui o AAD Pod Identity):

  • Anote a conta de serviço do pod com o identificador de cliente da identidade de carga de trabalho.
  • O arquivo de token federado do pod é detectado sozinho, por AZURE_FEDERATED_TOKEN_FILE.
  • O model.auth_mode: entra_id funciona sem mais nenhuma mudança.

Entidade de serviço em CI:

  • Defina AZURE_TENANT_ID, AZURE_CLIENT_ID e AZURE_CLIENT_SECRET no ambiente do executor.

Nuvens soberanas (Governo, China)​

Exporte o AZURE_AUTHORITY_HOST (por exemplo, https://login.microsoftonline.us no Azure Government, https://login.partner.microsoftonline.cn no Azure China). O azure-identity lê direto.

Verificações de saúde​

O hermes doctor roda uma sondagem de 10 segundos contra o DefaultAzureCredential quando model.auth_mode: entra_id, informando qual credencial interna venceu (variáveis de ambiente presentes, endpoint de identidade gerenciada alcançável etc.).

O hermes auth mostra um bloco de estado estruturado:

azure-foundry (Microsoft Entra ID):
Endpoint: https://my-resource.openai.azure.com/openai/v1
Scope: https://ai.azure.com/.default
Status: configured; live token probe is skipped here

Limitações​

  • Endpoints no estilo Anthropic usam um gancho de evento do httpx. O SDK Python da Anthropic não aceita auth_token chamável nativamente (até a 0.86.0). O Hermes instala um gancho num httpx.Client próprio, que gera um JWT novo por requisição e reescreve Authorization: Bearer <jwt>. É funcionalmente equivalente ao contrato nativo Callable[[], str] do SDK da OpenAI, mas acrescenta uma camada de indireção. Se o SDK da Anthropic passar a suportar autenticação chamável de primeira classe, o Hermes muda de forma transparente.
  • Tarefas em lote e multiprocessing.Pool. O provedor de token do Entra é um fechamento que não pode ser serializado entre processos. O batch_runner.py tira o chamável da configuração do trabalhador sozinho e deixa cada processo reconstruir o próprio provedor a partir do config.yaml — nada a fazer, mas cada trabalhador paga uma passada pela cadeia na inicialização.
  • Sem persistência do JWT no auth.json. O Hermes não duplica o cache interno de token do azure-identity; partidas frias percorrem a cadeia na primeira inferência.

Configuração (gravada no config.yaml)​

Depois do assistente, você vê algo assim:

model:
provider: azure-foundry
base_url: https://meu-recurso.openai.azure.com/openai/v1
api_mode: chat_completions # ou "anthropic_messages"
default: gpt-5.4-mini # o nome da sua implantação ou modelo
context_length: 400000 # detectado sozinho

E, em ~/.hermes/.env:

AZURE_FOUNDRY_API_KEY=<sua-chave-do-azure>

Endpoints no estilo OpenAI (GPT, Llama e outros)​

O endpoint v1 do Azure OpenAI aceita o cliente Python openai padrão, com mudanças mínimas:

model:
provider: azure-foundry
base_url: https://meu-recurso.openai.azure.com/openai/v1
api_mode: chat_completions
default: gpt-5.4

Comportamentos importantes:

  • GPT-5.x, codex e a série o vão para a API de Responses sozinhos. O Foundry implanta os modelos GPT-5, codex, o1, o3 e o4 apenas na API de Responses — chamar /chat/completions neles devolve 400 "The requested operation is unsupported.". O Hermes detecta essas famílias pelo nome e sobe o api_mode para codex_responses de forma transparente, mesmo com o config.yaml ainda dizendo api_mode: chat_completions. GPT-4, GPT-4o, Llama, Mistral e as outras implantações continuam em /chat/completions.
  • O max_completion_tokens é usado sozinho. O Azure OpenAI (como a OpenAI direta) exige max_completion_tokens nos modelos gpt-4o, da série o e gpt-5.x. O Hermes manda o parâmetro certo conforme o endpoint.
  • Endpoints anteriores à v1, que exigem api-version. Se você tem uma URL antiga, como https://<recurso>.openai.azure.com/openai?api-version=2025-04-01-preview, o Hermes extrai a consulta e a repassa por default_query em toda requisição (senão o SDK da OpenAI a descarta ao juntar os caminhos).

Endpoints no estilo Anthropic (Claude pelo Foundry)​

Para implantações de Claude, use a rota no estilo Anthropic:

model:
provider: azure-foundry
base_url: https://meu-recurso.services.ai.azure.com/anthropic
api_mode: anthropic_messages
default: claude-sonnet-4-6

Comportamentos importantes:

  • O /v1 é retirado da URL base. O SDK da Anthropic acrescenta /v1/messages a toda URL — o Hermes remove qualquer /v1 no fim antes de entregar a URL ao SDK, para não gerar caminhos com /v1 duplicado.
  • O api-version vai por default_query, não na URL. O Anthropic do Azure exige uma consulta api-version. Embutir na URL base produz caminhos malformados, como /anthropic?api-version=.../v1/messages, e devolve 404. O Hermes passa api-version=2025-04-15 pelo default_query do SDK.
  • A autenticação é por Bearer, não por x-api-key. A rota compatível com Anthropic do Azure exige Authorization: Bearer <chave>, e não o cabeçalho nativo x-api-key da Anthropic. O Hermes detecta azure.com na URL base e passa a chave pelo campo auth_token do SDK, para o cabeçalho certo chegar do outro lado.
  • O cabeçalho beta de 1 milhão de tokens é mantido. O Azure ainda controla o contexto de 1 milhão de tokens do Claude (Opus 4.6 e 4.7, Sonnet 4.6) pelo cabeçalho anthropic-beta: context-1m-2025-08-07. O Hermes mantém esse cabeçalho nos caminhos do Azure (ele é retirado nas requisições OAuth nativas da Anthropic, porque algumas assinaturas o recusam, mas o Azure exige).
  • A renovação de token OAuth é desligada. Implantações do Azure usam chaves estáticas. O laço de renovação de token do ~/.claude/.credentials.json, que vale para o Console da Anthropic, é explicitamente pulado nos endpoints do Azure, para o token OAuth do Claude Code não sobrescrever a sua chave do Azure no meio da sessão.

Alternativa: provider: anthropic com URL base do Azure​

Se você já tem provider: anthropic configurado e só quer apontá-lo para o Foundry, dá para pular o provedor azure-foundry:

model:
provider: anthropic
base_url: https://meu-recurso.services.ai.azure.com/anthropic
key_env: AZURE_ANTHROPIC_KEY
default: claude-sonnet-4-6

Com o AZURE_ANTHROPIC_KEY definido em ~/.hermes/.env. O Hermes detecta azure.com na URL base e contorna a cadeia de token OAuth do Claude Code, para a chave do Azure ser usada direto, com autenticação x-api-key.

O key_env é o nome canônico do campo; api_key_env (e as variantes keyEnv e apiKeyEnv) são aceitos como apelidos. Se o key_env e o AZURE_ANTHROPIC_KEY ou ANTHROPIC_API_KEY estiverem todos definidos, vence a variável nomeada pelo key_env.

Descoberta de modelos​

O Azure não expõe um endpoint que liste as suas implantações só com chave de API. Enumerar implantações exige autenticação no Azure Resource Manager (az cognitiveservices account deployment list), com uma entidade do Azure AD — não com a chave de inferência.

O que o Hermes consegue fazer:

  • Endpoints v1 do Azure OpenAI (<recurso>.openai.azure.com/openai/v1) expõem GET /models, com o catálogo de modelos disponíveis no recurso. O Hermes usa essa lista para preencher o seletor.
  • Rotas /anthropic do Foundry: detectadas pelo caminho da URL, com o nome do modelo digitado na mão.
  • Endpoints privados ou atrás de firewall: entrada manual, com uma mensagem amigável de "não deu para sondar".

Você sempre pode digitar o nome de uma implantação direto — o Hermes não valida contra a lista devolvida.

Variáveis de ambiente​

VariávelPara que serve
AZURE_FOUNDRY_API_KEYChave principal do Foundry ou do Azure OpenAI (modo de chave)
AZURE_FOUNDRY_BASE_URLURL do endpoint (definida pelo hermes model; a variável serve de reserva)
AZURE_ANTHROPIC_KEYUsada por provider: anthropic com URL base do Azure (alternativa ao ANTHROPIC_API_KEY)
AZURE_TENANT_IDLocatário do Entra ID, em fluxos de entidade de serviço
AZURE_CLIENT_IDIdentificador de cliente do Entra ID (entidade de serviço, identidade de carga de trabalho, ou identidade gerenciada atribuída pelo usuário)
AZURE_CLIENT_SECRETSegredo da entidade de serviço
AZURE_CLIENT_CERTIFICATE_PATHCertificado da entidade de serviço (alternativa ao segredo)
AZURE_FEDERATED_TOKEN_FILECaminho do token federado de identidade de carga de trabalho (AKS)
AZURE_AUTHORITY_HOSTTroca a autoridade, para nuvens soberanas
IDENTITY_ENDPOINT / MSI_ENDPOINTEndpoint de identidade gerenciada no App Service, no Functions e no Container Apps; máquinas virtuais costumam usar o IMDS

O SDK do Azure lê as variáveis AZURE_* diretamente. O Hermes nunca as inspeciona, a não ser para informar quais fontes existem, na saída do hermes doctor.

Resolução de problemas​

401 Unauthorized em implantações gpt-5.x. O Azure serve gpt-5.x em /chat/completions, não em /responses. O Hermes cuida disso sozinho quando a URL contém openai.azure.com, mas, se você vir um 401 com corpo de Invalid API key, confira se o api_mode do seu config.yaml é chat_completions.

404 em /v1/messages?api-version=.../v1/messages. É o bug de URL malformada das instalações antigas do Anthropic no Azure. Atualize o Hermes — o parâmetro api-version agora vai por default_query, em vez de ser embutido na URL base, então o SDK não consegue corrompê-lo ao juntar caminhos.

O assistente diz "Auto-detection incomplete". O endpoint recusou tanto a sondagem de /models quanto a de mensagens da Anthropic. É normal em endpoints privados, atrás de firewall ou com lista de IPs permitidos. Escolha o modo de API na mão e digite o nome da implantação — tudo funciona, o Hermes só não consegue preencher o seletor.

Transporte errado escolhido. Rode hermes model de novo e o assistente sonda outra vez. Se ele insistir no modo errado, edite o config.yaml:

model:
provider: azure-foundry
api_mode: anthropic_messages # ou chat_completions

Entra ID: "credential chain exhausted", ou 401 depois de mudar para auth_mode: entra_id.

  • Rode az login para renovar a sessão de desenvolvimento (o token em cache pode ter expirado).
  • Confirme que a atribuição do papel Azure AI User (ou Foundry User) valeu: az role assignment list --assignee <id-do-usuário-ou-identidade> deve listá-la no recurso. A propagação leva até 5 minutos.
  • Em identidades gerenciadas atribuídas pelo usuário, confira se o AZURE_CLIENT_ID bate com a identidade anexada ao recurso de computação.
  • Rode hermes doctor — a sondagem do Entra informa se a obtenção do token funcionou, com uma dica de correção.

Entra ID: a sondagem prévia do assistente trava ou estoura o tempo. Os 10 segundos são uma checagem branda. Escolha "salvar assim mesmo, validar depois" e rode o hermes doctor depois de implantar no ambiente de destino. As causas comuns são um serviço de token inalcançável ou uma sessão local velha — prefira identidade de carga de trabalho em CI, defina AZURE_TENANT_ID, AZURE_CLIENT_ID e AZURE_CLIENT_SECRET com entidade de serviço, ou rode az login no desenvolvimento local.

401 no endpoint estilo Anthropic, com Entra ID. Confirme que o mesmo papel Azure AI User (ou Foundry User) está atribuído no recurso do Foundry (ele cobre tanto /openai/v1 quanto /anthropic). Se a sondagem no estilo OpenAI funciona no assistente mas as requisições claude-* falham em execução, a causa mais comum é um model.entra.scope velho, sobrando de uma configuração anterior — apague a linha entra.scope do config.yaml, para o runtime voltar ao escopo padrão https://ai.azure.com/.default.