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.
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.progresspara 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_callefunction_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
- Envie um
POST /v1/browser-control/registerautenticado, comprotocol_version,session_id,controller_id,browser_profile_ide ascapabilitiespedidas. - O Hermes devolve um ticket de uso único, com TTL de 30 segundos, e o escopo de controlador filtrado e vinculado ao servidor.
- Abra
GET /v1/browser-control/wscom os dois subprotocolos de WebSocket:hermes-browser-control-v1ehermes-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 turnoprovider— o slug de provedor do Hermes para resolver credenciais/runtime deste turnomodel_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/completionsPOST /v1/responsesPOST /v1/runsPOST /api/sessions/{session_id}/chatPOST /api/sessions/{session_id}/chat/stream
A precedência é determinística:
- A sobreposição de
/modelda sessão, se aquela sessão já tiver uma - Um mapeamento estático
gateway.platforms.api_server.model_routes, escolhido quando omodelda requisição é um alias de rota configurado - O
model/providerdireto da requisição, quando nenhum alias de rota casa - 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étodo | Caminho | Descrição |
|---|---|---|
GET | /api/sessions | Lista as sessões (paginado — limit, offset, source, include_children) |
POST | /api/sessions | Cria 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}/messages | Histórico de mensagens de uma sessão |
POST | /api/sessions/{id}/fork | Ramifica a sessão pela linhagem do SessionDB (mesma semântica do /branch na CLI) |
POST | /api/sessions/{id}/chat | Roda um turno síncrono do agente |
POST | /api/sessions/{id}/chat/stream | Camada 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 aAPI_SERVER_KEYdaquele 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_KEYprópria falha fechado — o prefixo dele fica inacessível até você definir uma.
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.
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ável | Padrão | Descrição |
|---|---|---|
API_SERVER_ENABLED | false | Habilita o servidor de API |
API_SERVER_PORT | 8642 | Porta do servidor HTTP |
API_SERVER_HOST | 127.0.0.1 | Endereç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 MIMEReferrer-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:
| Frontend | Estrelas | Conexão |
|---|---|---|
| Open WebUI | 126k | Guia completo disponível |
| LobeChat | 73k | Endpoint de provedor personalizado |
| LibreChat | 34k | Endpoint personalizado no librechat.yaml |
| AnythingLLM | 56k | Provedor genérico da OpenAI |
| NextChat | 87k | Variável de ambiente BASE_URL |
| ChatBox | 39k | Configuração de API Host |
| Jan | 26k | Configuração de modelo remoto |
| HF Chat-UI | 8k | OPENAI_BASE_URL |
| big-AGI | 7k | Endpoint 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→ modeloalicehttp://localhost:8644/v1/models→ modelobob
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/completionsquanto 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/modelsanuncia o alias estável do Hermes (hermes-agentou o nome do perfil ativo). Clientes mais ricos podem enviar sobreposições explícitas deprovider/model_optionsnas 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.