Pular para o conteúdo principal

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

Servidor de API

O servidor de API expõe o hermes-agent como um endpoint HTTP compatível com a OpenAI. Qualquer frontend que fale o formato da OpenAI — Open WebUI, LobeChat, LibreChat, NextChat, ChatBox e centenas de outros — pode se conectar ao hermes-agent e usá-lo como backend.

Seu agente atende as requisições com o conjunto completo de ferramentas (terminal, operações de arquivo, busca na web, memória, skills) e devolve a resposta final. Em streaming, os indicadores de progresso das ferramentas aparecem no meio do fluxo, para que os frontends mostrem o que o agente está fazendo.

Um backend cobre modelos + ferramentas

O próprio Hermes precisa de um provedor configurado e de backends de ferramenta para o servidor de API ser útil. Uma assinatura do Nous Portal resolve os dois — mais de 300 modelos, além de web/imagem/TTS/navegador pelo Tool Gateway. Rode hermes setup --portal uma vez antes de subir o servidor de API, e frontends como Open WebUI ou LobeChat ganham um backend totalmente equipado de ferramentas.

Início rápido​

1. Habilite o servidor de API​

Adicione ao ~/.hermes/.env:

API_SERVER_ENABLED=true
API_SERVER_KEY=change-me-local-dev
# Opcional: só se um navegador precisar chamar o Hermes direto
# API_SERVER_CORS_ORIGINS=http://localhost:3000

2. Suba o gateway​

hermes gateway

Você vai ver:

[API Server] API server listening on http://127.0.0.1:8642

3. Conecte um frontend​

Aponte qualquer cliente compatível com a OpenAI para http://localhost:8642/v1:

# Teste com curl
curl http://localhost:8642/v1/chat/completions \
-H "Authorization: Bearer change-me-local-dev" \
-H "Content-Type: application/json" \
-d '{"model": "hermes-agent", "messages": [{"role": "user", "content": "Hello!"}]}'

Ou conecte o Open WebUI, o LobeChat ou qualquer outro frontend — veja o guia de integração do Open WebUI para as instruções passo a passo.

Endpoints​

POST /v1/chat/completions​

Formato padrão de Chat Completions da OpenAI. Sem estado — a conversa inteira vai em cada requisição pelo array messages.

Requisição:

{
"model": "hermes-agent",
"messages": [
{"role": "system", "content": "You are a Python expert."},
{"role": "user", "content": "Write a fibonacci function"}
],
"stream": false
}

Resposta:

{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1710000000,
"model": "hermes-agent",
"choices": [{
"index": 0,
"message": {"role": "assistant", "content": "Here's a fibonacci function..."},
"finish_reason": "stop"
}],
"usage": {"prompt_tokens": 50, "completion_tokens": 200, "total_tokens": 250}
}

Entrada de imagem no corpo da mensagem: as mensagens de usuário podem mandar content como um array de partes text e image_url. Tanto URLs remotas http(s) quanto URLs data:image/... são suportadas:

{
"model": "hermes-agent",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "What is in this image?"},
{"type": "image_url", "image_url": {"url": "https://example.com/cat.png", "detail": "high"}}
]
}
]
}

Arquivos enviados (file / input_file / file_id) e URLs data: que não sejam de imagem devolvem 400 unsupported_content_type.

Streaming ("stream": true): devolve Server-Sent Events (SSE) com pedaços de resposta token por token. Em Chat Completions, o fluxo usa os eventos padrão chat.completion.chunk mais o evento próprio do Hermes hermes.tool.progress, para a experiência de início de ferramenta. Em Responses, o fluxo usa os tipos de evento da Responses da OpenAI, como response.created, response.output_text.delta, response.output_item.added, response.output_item.done e response.completed.

Progresso de ferramenta nos fluxos:

  • Chat Completions: o Hermes emite event: hermes.tool.progress para dar visibilidade ao início da ferramenta sem sujar o texto persistido do assistente.
  • Responses: o Hermes emite itens de saída nativos da especificação, function_call e function_call_output, durante o fluxo SSE, para que os clientes desenhem uma interface estruturada de ferramentas em tempo real.

POST /v1/responses​

Formato da API Responses da OpenAI. Suporta estado de conversa no servidor via previous_response_id — o servidor guarda o histórico completo da conversa (inclusive chamadas de ferramenta e resultados), então o contexto de vários turnos é preservado sem o cliente ter que administrar isso.

Requisição:

{
"model": "hermes-agent",
"input": "What files are in my project?",
"instructions": "You are a helpful coding assistant.",
"store": true
}

Resposta:

{
"id": "resp_abc123",
"object": "response",
"status": "completed",
"model": "hermes-agent",
"output": [
{"type": "function_call", "status": "completed", "name": "terminal", "arguments": "{\"command\": \"ls\"}", "call_id": "call_1"},
{"type": "function_call_output", "status": "completed", "call_id": "call_1", "output": "README.md src/ tests/"},
{"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "Your project has..."}]}
],
"usage": {"input_tokens": 50, "output_tokens": 200, "total_tokens": 250}
}

As chamadas de ferramenta no array output já foram executadas no servidor pelo agente Hermes — elas são reapresentadas com "status": "completed" para montar uma interface estruturada de ferramentas, nunca como chamadas pendentes para o cliente executar.

Entrada de imagem no corpo da mensagem: input[].content pode conter partes input_text e input_image. Tanto URLs remotas quanto URLs data:image/... são suportadas:

{
"model": "hermes-agent",
"input": [
{
"role": "user",
"content": [
{"type": "input_text", "text": "Describe this screenshot."},
{"type": "input_image", "image_url": "data:image/png;base64,iVBORw0K..."}
]
}
]
}

Arquivos enviados (input_file / file_id) e URLs data: que não sejam de imagem devolvem 400 unsupported_content_type.

Vários turnos com previous_response_id​

Encadeie respostas para manter o contexto completo (inclusive chamadas de ferramenta) entre turnos:

{
"input": "Now show me the README",
"previous_response_id": "resp_abc123"
}

O servidor reconstrói a conversa inteira a partir da cadeia de respostas guardadas — todas as chamadas de ferramenta e resultados anteriores são preservados. Requisições encadeadas também compartilham a mesma sessão, então conversas de vários turnos aparecem como uma única entrada no painel e no histórico de sessões.

Conversas nomeadas​

Use o parâmetro conversation em vez de acompanhar IDs de resposta:

{"input": "Hello", "conversation": "my-project"}
{"input": "What's in src/?", "conversation": "my-project"}
{"input": "Run the tests", "conversation": "my-project"}

O servidor encadeia automaticamente na resposta mais recente daquela conversa. É como o comando /title para as sessões do gateway.

GET /v1/responses/{id}​

Recupera pelo ID uma resposta guardada antes.

DELETE /v1/responses/{id}​

Apaga uma resposta guardada.

GET /v1/models​

Lista o agente como um modelo disponível. O nome de modelo anunciado assume por padrão o nome do perfil (ou hermes-agent, para o perfil padrão). Exigido pela maioria dos frontends para descobrir modelos.

O /v1/models é, de propósito, a superfície barata de compatibilidade com a OpenAI. Ele não enumera toda combinação de provedor/modelo autenticada para a qual o Hermes consegue rotear, e não faz enriquecimento de preços nem de capacidades.

GET /api/model/options​

Clientes que conhecem o Hermes podem pedir o mesmo inventário curado de provedor/modelo usado pelo painel e pela TUI. Essa rota usa a autenticação normal por bearer do servidor de API e devolve linhas de provedor, dicas de capacidade de modelo e metadados de preço que não cabem na resposta compatível com a OpenAI do /v1/models:

curl \
-H "Authorization: Bearer $API_SERVER_KEY" \
"http://127.0.0.1:8642/api/model/options"

Esse payload é o mesmo substrato usado pela página de Modelos do painel e pelo RPC model.options da TUI. Ele devolve provedores autenticados, listas curadas de modelos, preços por modelo e dicas de capacidade de modelo.

Aberturas normais são conservadoras de propósito para provedores personalizados: o Hermes sonda só o endpoint personalizado selecionado no momento, para que um endpoint salvo desatualizado ou fora do ar não travar o seletor. Uma atualização explícita passa para a sondagem completa e invalida o cache de modelos do provedor:

curl \
-H "Authorization: Bearer $API_SERVER_KEY" \
"http://127.0.0.1:8642/api/model/options?refresh=1"

Use o /v1/models quando um cliente compatível com a OpenAI só precisa de um nome de modelo para devolver nas requisições de chat/responses. Use o /api/model/options quando uma interface autenticada precisa dos metadados mais ricos e específicos do Hermes para o seletor.

GET /v1/capabilities​

Devolve uma descrição legível por máquina da superfície estável do servidor de API, para interfaces externas, orquestradores e pontes de plugin.

{
"object": "hermes.api_server.capabilities",
"platform": "hermes-agent",
"model": "hermes-agent",
"auth": {"type": "bearer", "required": true},
"features": {
"chat_completions": true,
"responses_api": true,
"run_submission": true,
"run_status": true,
"run_events_sse": true,
"run_stop": true
}
}

Use este endpoint ao integrar painéis, interfaces de navegador ou planos de controle, para que eles descubram se a versão do Hermes em execução suporta runs, streaming, cancelamento e continuidade de sessão sem depender de internos privados do Python.

Controle por extensão de navegador​

O Hermes pode rotear as ferramentas de navegador por uma extensão autenticada que controla a sessão de navegador associada à sessão atual do Hermes. O recurso vem desabilitado por padrão; defina browser.extension_control.enabled como true para ativar:

browser:
extension_control:
enabled: true

O caminho da API local também exige a chave bearer do servidor de API. Um controlador só pode se registrar para uma sessão de servidor que já existe. O Hermes deriva o principal do controlador a partir do estado autenticado do servidor; um principal_id fornecido pelo cliente é ignorado.

Descubra o contrato vivo pelo GET /v1/capabilities. O objeto browser_extension_control informa se o recurso está habilitado, a versão do protocolo, os nomes de transporte e a lista exata de capacidades permitidas:

controller.noop
browser_back
browser_click
browser_navigate
browser_press
browser_screenshot
browser_scroll
browser_snapshot
browser_tab_activate
browser_tabs
browser_type

Capacidades pedidas fora dessa lista são filtradas. CDP bruto, avaliação arbitrária de script, acesso ao console, envios de arquivo, extração de imagem e visão não fazem parte do protocolo do controlador.

Quando uma requisição não tem identidade de controlador vinculada, ou quando o recurso está desabilitado, o Hermes preserva o backend de navegador existente. Uma vez que o gateway vincula um principal de controlador e uma família de transporte à requisição, aquela faixa da extensão passa a ser a autoridade: controladores ausentes, ambíguos, desconectados ou incapazes falham fechado em vez de trocar em silêncio para outro navegador local/em nuvem. Depois que um controlador exato é selecionado, o resultado ou o erro dele é a autoridade e o Hermes nunca repete a mesma ação por outro backend.

Registro pela API local​

  1. Envie um POST /v1/browser-control/register autenticado, com protocol_version, session_id, controller_id, browser_profile_id e as capabilities pedidas.
  2. O Hermes devolve um ticket de uso único, com TTL de 30 segundos, e o escopo de controlador filtrado e vinculado ao servidor.
  3. Abra GET /v1/browser-control/ws com os dois subprotocolos de WebSocket: hermes-browser-control-v1 e hermes-browser-control-ticket.<ticket>.

O ticket nunca é aceito na query string. Tickets desconhecidos, expirados, reutilizados ou malformados falham antes do upgrade de WebSocket.

Quadros do controlador​

O Hermes envia quadros browser.controller.command contendo command_id, action, arguments imutáveis, ids de navegador/controlador e o tool_call_id de origem. O controlador responde com browser.controller.result, o mesmo command_id, um booleano exato ok, e result ou error. Cancelamento e tempo esgotado emitem browser.controller.cancel; resultados atrasados são ignorados.

Uma perda inesperada de socket marca o controlador como fora do ar e preserva o trabalho já em andamento até o prazo original de cada comando. Uma reconexão com o mesmo principal, perfil, sessão, id de controlador, perfil de navegador e identidade de transporte renova o transporte sem admitir trabalho novo antes de os cancelamentos adiados serem descarregados. As capacidades negociadas podem mudar nessa reconexão; elas não são um campo de identidade. Um id de controlador ou perfil de navegador diferente na mesma faixa de sessão autenticada é uma substituição dura: o trabalho pendente antigo é cancelado antes de o sucessor virar roteável. Envie browser.controller.detach no transporte autenticado do controlador para um desligamento duro intencional — isso cancela na hora o trabalho pendente. Só fechar o socket é tratado como uma desconexão recuperável.

O transporte autenticado do painel expõe a mesma semântica de registro, resultado, heartbeat, capacidade e posse pelo canal de RPC/eventos do Gateway. Nos dois transportes, a seleção exige uma única correspondência exata e não ambígua de principal, perfil, sessão, controlador, perfil de navegador, família de transporte e capacidade. Depois de selecionada, uma falha do controlador é a autoridade e nunca é repetida por outro backend de navegador.

Seleção de modelo por requisição​

Clientes autenticados podem sobrepor a seleção padrão de modelo do Hermes em cada requisição enviando:

  • model — o id do modelo de destino para este turno
  • provider — o slug de provedor do Hermes para resolver credenciais/runtime deste turno
  • model_options — controles de raciocínio / camada de serviço no escopo da requisição

Os mesmos campos de requisição são aceitos em:

  • POST /v1/chat/completions
  • POST /v1/responses
  • POST /v1/runs
  • POST /api/sessions/{session_id}/chat
  • POST /api/sessions/{session_id}/chat/stream

A precedência é determinística:

  1. A sobreposição de /model da sessão, se aquela sessão já tiver uma
  2. Um mapeamento estático gateway.platforms.api_server.model_routes, escolhido quando o model da requisição é um alias de rota configurado
  3. O model / provider direto da requisição, quando nenhum alias de rota casa
  4. Config global do gateway / padrões de ambiente

O model_options continua no escopo da requisição, não importa qual modelo/provedor ganhe. Se uma requisição manda um provider que conflita com um alias configurado em model_routes, o Hermes rejeita a requisição com 400 em vez de misturar em silêncio as credenciais da rota com outro provedor.

Valores de model avulsos nos endpoints compatíveis com a OpenAI precisam ser ativados. Clientes genéricos da OpenAI cravam nomes de modelo com frequência (gpt-4o, ...), e implantações existentes contam com esses nomes caindo no padrão do gateway. Em POST /v1/chat/completions e POST /v1/responses, um valor de model enviado SEM um provider é, portanto, ignorado, a menos que você habilite:

gateway:
platforms:
api_server:
direct_model_requests: true

Requisições que incluem um provider explícito — e os endpoints nativos do Hermes /v1/runs e de chat de sessão — sempre respeitam o modelo pedido, independentemente dessa flag.

Exemplo:

{
"model": "MiniMax-M3",
"provider": "minimax",
"model_options": {
"reasoning_effort": "high",
"service_tier": "priority"
},
"messages": [
{"role": "user", "content": "Summarize the repo status."}
]
}

GET /health​

Verificação de saúde. Devolve {"status": "ok"}. Também está disponível em GET /v1/health, para clientes compatíveis com a OpenAI que esperam o prefixo /v1/.

GET /health/detailed​

Verificação de prontidão autenticada, para monitoramento e planos de controle. Ela informa o estado, de forma limitada, da configuração do perfil ativo, do banco de estado, do modelo configurado, do espaço em disco, do estado de gateway/plataforma, das runs ativas da API, das conclusões de processo pendentes e das delegações ativas. A resposta expõe estado e contagens, não valores de configuração, credenciais, caminhos, comandos, payloads de fila nem erros crus.

A rota pública /health continua sendo uma sonda barata de vitalidade e não roda verificações de prontidão. Um resultado de prontidão degradado ainda usa HTTP 200; inspecione os campos status do nível de cima e readiness.checks.

API de runs (alternativa amiga de streaming)​

Além de /v1/chat/completions e /v1/responses, o servidor expõe uma API de runs para sessões longas em que o cliente quer se inscrever em eventos de progresso em vez de administrar o streaming por conta própria.

POST /v1/runs​

Cria uma nova run do agente. Devolve um run_id que pode ser usado para se inscrever nos eventos de progresso.

{
"run_id": "run_abc123",
"status": "started"
}

As runs aceitam um input simples em texto e, opcionalmente, session_id, instructions, conversation_history ou previous_response_id. Quando um session_id é informado, o Hermes o expõe no estado da run, para que interfaces externas correlacionem runs com os próprios IDs de conversa.

GET /v1/runs/{run_id}​

Consulta o estado atual da run. É útil para painéis que precisam do estado sem manter uma conexão SSE aberta, ou para interfaces que reconectam depois de uma navegação.

{
"object": "hermes.run",
"run_id": "run_abc123",
"status": "completed",
"session_id": "space-session",
"model": "hermes-agent",
"output": "Done.",
"usage": {"input_tokens": 50, "output_tokens": 200, "total_tokens": 250}
}

Os estados são mantidos por um tempinho depois dos estados finais (completed, failed ou cancelled), para consulta e reconciliação de interface.

GET /v1/runs/{run_id}/events​

Fluxo de Server-Sent Events com o progresso das chamadas de ferramenta da run, os deltas de token e os eventos de ciclo de vida. Feito para painéis e clientes pesados que querem se conectar e desconectar sem perder estado.

Quando o agente delega trabalho a subagentes em segundo plano, o fluxo também carrega eventos de ciclo de vida subagent.start e subagent.complete, para que os clientes observem os desfechos da delegação — inclusive tempos esgotados e falhas — em vez de a run ficar muda enquanto um filho trabalha. O payload de subagent.complete carrega o estado do filho, o resumo, a duração, os números de token/custo e um child_session_id para correlação; os campos de texto livre passam por censura forçada de segredos antes de sair do processo. Eventos de ferramenta por filho (subagent.tool, tiques de progresso) não são repassados de propósito — eles são ruído de alto volume na interface; use os arquivos de transcrição ao vivo por filho para o lance a lance.

Buffers de evento não consumidos expiram depois de cinco minutos, para que um cliente desconectado não faça a memória crescer sem limite. Isso expira só o estado de transporte: uma run que ainda está executando continua visível para consulta de estado, aprovação, controle de parada e contabilidade de concorrência até o trabalho no executor realmente sair. Um inscrito de SSE conectado continua drenando normalmente.

POST /v1/runs/{run_id}/stop​

Interrompe um turno do agente em execução. O endpoint devolve na hora {"status": "stopping"} enquanto o Hermes pede ao agente ativo para parar no próximo ponto seguro de interrupção. A run continua rastreada como stopping até o trabalho no executor sair, e então se acomoda como cancelled; pedir para parar nunca esconde um trabalhador que ainda está rodando.

POST /v1/runs/{run_id}/approval​

Resolve uma aprovação pendente de uma run que está esperando uma decisão humana (por exemplo, uma chamada de ferramenta barrada por uma política de aprovação). O corpo carrega a decisão de aprovação; a run retoma quando a decisão é registrada. Este endpoint é anunciado no /v1/capabilities como o recurso run_approval, para que interfaces externas detectem o suporte antes de mostrar um pedido de aprovação.

API de jobs (trabalho agendado em segundo plano)​

O servidor expõe uma superfície leve de CRUD de jobs para administrar runs de agente agendadas / em segundo plano a partir de um cliente remoto. Todos os endpoints ficam atrás da mesma autenticação por bearer.

GET /api/jobs​

Lista todas as tarefas agendadas.

POST /api/jobs​

Cria uma nova tarefa agendada. O corpo aceita o mesmo formato do hermes cron — prompt, agendamento, skills, sobreposição de provedor, destino de entrega.

GET /api/jobs/{job_id}​

Busca a definição de uma tarefa e o estado da última execução.

PATCH /api/jobs/{job_id}​

Atualiza campos de uma tarefa existente (prompt, agendamento etc.). Atualizações parciais são mescladas.

DELETE /api/jobs/{job_id}​

Remove uma tarefa. Também cancela qualquer execução em andamento.

POST /api/jobs/{job_id}/pause​

Pausa uma tarefa sem apagá-la. Os horários da próxima execução agendada ficam suspensos até você retomar.

POST /api/jobs/{job_id}/resume​

Retoma uma tarefa pausada antes.

POST /api/jobs/{job_id}/run​

Dispara a tarefa para rodar na hora, fora do agendamento.

API de sessões (controle de sessão por REST)​

Interfaces externas podem administrar sessões do Hermes por REST, sem subir o painel. Todos os endpoints ficam atrás da API_SERVER_KEY e moram em /api/sessions/*.

MétodoCaminhoDescrição
GET/api/sessionsLista as sessões (paginado — limit, offset, source, include_children)
POST/api/sessionsCria uma sessão vazia
GET/api/sessions/{id}Lê os metadados da sessão
PATCH/api/sessions/{id}Atualiza o título ou o end_reason
DELETE/api/sessions/{id}Apaga uma sessão
GET/api/sessions/{id}/messagesHistórico de mensagens de uma sessão
POST/api/sessions/{id}/forkRamifica a sessão pela linhagem do SessionDB (mesma semântica do /branch na CLI)
POST/api/sessions/{id}/chatRoda um turno síncrono do agente
POST/api/sessions/{id}/chat/streamCamada SSE sobre um único turno — emite os eventos assistant.delta, tool.started, tool.completed e run.completed

O /v1/capabilities anuncia a superfície inteira pelas flags de recurso session_* e pelas entradas endpoints.session_*, para que interfaces externas detectem o suporte e recuem com segurança. Imagens no corpo da mensagem são suportadas nos payloads de chat e chat/stream (caminho que entende multimodal).

# ramifica uma sessão e roda um turno
curl -X POST http://localhost:8642/api/sessions/$ID/fork \
-H "Authorization: Bearer $API_SERVER_KEY" \
-d '{"title": "explore alt path"}'

# transmite um turno por SSE
curl -N -X POST http://localhost:8642/api/sessions/$ID/chat/stream \
-H "Authorization: Bearer $API_SERVER_KEY" \
-d '{"input": "what files changed in the last hour?"}'

Descoberta de skills e conjuntos de ferramentas​

O GET /v1/skills e o GET /v1/toolsets deixam clientes externos enumerarem as capacidades do agente de forma determinística por REST, em vez de perguntar ao modelo. Os dois são somente leitura e ficam atrás da API_SERVER_KEY.

curl http://localhost:8642/v1/skills \
-H "Authorization: Bearer $API_SERVER_KEY"
# → [{"name": "github-pr-workflow", "description": "...", "category": "..."}, ...]

curl http://localhost:8642/v1/toolsets \
-H "Authorization: Bearer $API_SERVER_KEY"
# → [{"name": "core", "label": "...", "description": "...", "enabled": true,
# "configured": true, "tools": ["read_file", "write_file", ...]}, ...]

O /v1/skills devolve os mesmos metadados que o hub de skills usa internamente. O /v1/toolsets devolve os conjuntos de ferramentas resolvidos para a plataforma api_server, com a lista concreta de tools em que cada um se expande. Os dois são anunciados em endpoints.* no /v1/capabilities.

Escopo de memória de longo prazo (X-Hermes-Session-Key)​

Frontends com vários usuários, como o Open WebUI, precisam de um identificador estável por canal para a memória de longo prazo (Honcho etc.) que seja independente do X-Hermes-Session-Id, que tem escopo de transcrição (e gira no /new). Passe o X-Hermes-Session-Key em /v1/chat/completions, /v1/responses ou /v1/runs e o Hermes o repassa até o AIAgent(gateway_session_key=...), onde o provedor de memória Honcho o usa para derivar um escopo estável.

POST /v1/chat/completions HTTP/1.1
Authorization: Bearer ***
X-Hermes-Session-Id: transcript-alpha
X-Hermes-Session-Key: agent:main:webui:dm:user-42

Regras: no máximo 256 caracteres, caracteres de controle (\r, \n, \x00) são rejeitados, e o valor é devolvido de volta nas respostas (JSON + SSE). O /v1/capabilities anuncia o suporte via "session_key_header": "X-Hermes-Session-Key". Sem a chave, a estratégia per-session do Honcho produz um escopo diferente por session_id — exatamente o comportamento que o Hermes tinha antes.

Tratamento do prompt de sistema​

Quando um frontend manda uma mensagem system (Chat Completions) ou o campo instructions (API Responses), o hermes-agent empilha isso em cima do prompt de sistema principal dele. Seu agente mantém todas as ferramentas, a memória e as skills — o prompt de sistema do frontend acrescenta instruções extras.

Isso quer dizer que você pode personalizar o comportamento por frontend sem perder capacidades:

  • Prompt de sistema no Open WebUI: "You are a Python expert. Always include type hints."
  • O agente continua com terminal, ferramentas de arquivo, busca na web, memória etc.

Autenticação​

Autenticação por token bearer, no cabeçalho Authorization:

Authorization: Bearer ***

Configure a chave pela variável de ambiente API_SERVER_KEY. Se você precisa que um navegador chame o Hermes direto, defina também o API_SERVER_CORS_ORIGINS com uma lista de permissão explícita.

Roteamento de vários perfis (/p/<profile>/…)​

Quando o roteamento de gateway com vários perfis está habilitado (gateway.multiplex_profiles), o ouvinte compartilhado atende todos os perfis por um prefixo de URL /p/<profile>/ — e a autenticação é vinculada ao perfil roteado:

  • Requisições para /p/<profile>/v1/... precisam apresentar a API_SERVER_KEY daquele perfil (de ~/.hermes/profiles/<profile>/.env). A chave do ouvinte padrão é rejeitada nos prefixos de perfil nomeado.
  • Rotas sem prefixo e /p/default/... continuam usando a chave do perfil padrão.
  • Um perfil nomeado sem uma API_SERVER_KEY própria falha fechado — o prefixo dele fica inacessível até você definir uma.
Mudança incompatível (julho de 2026)

Antes desta correção, uma chave válida do perfil padrão era aceita em qualquer prefixo /p/<profile>/. Se você contava com uma chave compartilhada entre os prefixos de perfil, defina uma API_SERVER_KEY distinta no .env de cada perfil — chaves padrão reutilizadas em prefixos nomeados agora devolvem 401.

Segurança

O servidor de API dá acesso total ao conjunto de ferramentas do hermes-agent, inclusive comandos de terminal. A API_SERVER_KEY é obrigatória em toda implantação, inclusive no bind padrão de loopback em 127.0.0.1. Mantenha o API_SERVER_CORS_ORIGINS restrito para controlar o acesso do navegador quando você permitir chamadores de navegador explicitamente.

Configuração​

Variáveis de ambiente​

VariávelPadrãoDescrição
API_SERVER_ENABLEDfalseHabilita o servidor de API
API_SERVER_PORT8642Porta do servidor HTTP
API_SERVER_HOST127.0.0.1Endereço de bind (só localhost, por padrão)
API_SERVER_KEY(obrigatória)Token bearer para autenticação
API_SERVER_CORS_ORIGINS(nenhuma)Origens de navegador permitidas, separadas por vírgula
API_SERVER_MODEL_NAME(nome do perfil)Nome do modelo no /v1/models. Assume por padrão o nome do perfil, ou hermes-agent para o perfil padrão.

config.yaml​

As mesmas configurações podem morar no ~/.hermes/config.yaml, numa seção aninhada gateway.api_server::

gateway:
api_server:
enabled: true
port: 8642
host: 127.0.0.1
key: sua-chave-secreta
cors_origins: http://localhost:3000
model_name: my-hermes
max_concurrent_runs: 10 # teto de runs simultâneas; 0 desliga o limite

port, key, host, cors_origins e model_name são automaticamente levados para as configurações extra da plataforma, então se comportam exatamente como as variáveis de ambiente API_SERVER_* equivalentes. As variáveis de ambiente têm precedência sobre os valores do config.yaml. O bloco também é aceito em gateway.platforms.api_server: ou numa seção platforms.api_server: no nível de cima.

Teto de runs simultâneas​

O servidor de API limita quantas runs de agente podem executar ao mesmo tempo, somando os endpoints compatíveis com a OpenAI e os de runs. O teto é lido de gateway.api_server.max_concurrent_runs (padrão 10; 0 desliga o limite, valores negativos são fixados em 0). Quando o teto é alcançado, novas requisições que iniciam runs são rejeitadas com HTTP 429 Too many concurrent runs (max N) — os clientes devem recuar e tentar de novo.

Cabeçalhos de segurança​

Todas as respostas incluem cabeçalhos de segurança:

  • X-Content-Type-Options: nosniff — impede a adivinhação de tipo MIME
  • Referrer-Policy: no-referrer — impede vazamento de referrer

CORS​

O servidor de API não habilita CORS de navegador por padrão.

Para acesso direto do navegador, defina uma lista de permissão explícita:

API_SERVER_CORS_ORIGINS=http://localhost:3000,http://127.0.0.1:3000

Quando o CORS está habilitado:

  • Respostas de preflight incluem Access-Control-Max-Age: 600 (cache de 10 minutos)
  • Respostas de streaming SSE incluem cabeçalhos de CORS, para que clientes EventSource de navegador funcionem direito
  • Idempotency-Key é um cabeçalho de requisição permitido — os clientes podem enviá-lo para desduplicação (as respostas ficam em cache por chave por 5 minutos)

A maioria dos frontends documentados, como o Open WebUI, conecta de servidor para servidor e não precisa de CORS nenhum.

Frontends compatíveis​

Qualquer frontend que suporte o formato da API da OpenAI funciona. Integrações testadas/documentadas:

FrontendEstrelasConexão
Open WebUI126kGuia completo disponível
LobeChat73kEndpoint de provedor personalizado
LibreChat34kEndpoint personalizado no librechat.yaml
AnythingLLM56kProvedor genérico da OpenAI
NextChat87kVariável de ambiente BASE_URL
ChatBox39kConfiguração de API Host
Jan26kConfiguração de modelo remoto
HF Chat-UI8kOPENAI_BASE_URL
big-AGI7kEndpoint personalizado
SDK Python da OpenAI—OpenAI(base_url="http://localhost:8642/v1")
curl—Requisições HTTP diretas

Configuração para vários usuários, com perfis​

Para dar a vários usuários uma instância isolada de Hermes (configuração, memória e skills separadas), use perfis:

# Crie um perfil por usuário
hermes profile create alice
hermes profile create bob

# Configure o servidor de API de cada perfil numa porta diferente. As API_SERVER_* são
# variáveis de ambiente (não chaves do config.yaml), então escreva no .env de cada perfil:
cat >> ~/.hermes/profiles/alice/.env <<EOF
API_SERVER_ENABLED=true
API_SERVER_PORT=8643
API_SERVER_KEY=alice-secret
EOF

cat >> ~/.hermes/profiles/bob/.env <<EOF
API_SERVER_ENABLED=true
API_SERVER_PORT=8644
API_SERVER_KEY=bob-secret
EOF

# Suba o gateway de cada perfil
hermes -p alice gateway &
hermes -p bob gateway &

O servidor de API de cada perfil anuncia automaticamente o nome do perfil como ID de modelo:

  • http://localhost:8643/v1/models → modelo alice
  • http://localhost:8644/v1/models → modelo bob

No Open WebUI, adicione cada um como uma conexão separada. A lista de modelos mostra alice e bob como modelos distintos, cada um sustentado por uma instância de Hermes totalmente isolada. Veja o guia do Open WebUI para os detalhes.

Limitações​

  • Armazenamento de respostas — as respostas guardadas (para o previous_response_id) são persistidas em SQLite e sobrevivem a reinícios do gateway. No máximo 100 respostas guardadas (descarte por LRU).
  • Sem envio de arquivo — imagens no corpo da mensagem são suportadas tanto em /v1/chat/completions quanto em /v1/responses, mas arquivos enviados (file, input_file, file_id) e entradas de documento que não sejam imagem não são suportados pela API.
  • Clientes simples da OpenAI continuam vendo um alias — o /v1/models anuncia o alias estável do Hermes (hermes-agent ou o nome do perfil ativo). Clientes mais ricos podem enviar sobreposições explícitas de provider / model_options nas requisições.

Modo proxy​

O servidor de API também serve de backend para o modo proxy de gateway. Quando outra instância de gateway do Hermes é configurada com o GATEWAY_PROXY_URL apontando para este servidor de API, ela encaminha todas as mensagens para cá em vez de rodar o próprio agente. Isso permite implantações divididas — por exemplo, um contêiner Docker cuidando do E2EE do Matrix e repassando para um agente na máquina hospedeira.

Veja Modo proxy do Matrix para o guia completo de configuração.