ワンクリックで
hermes-architecture
Arquitetura completa do Hermes Agent — credenciais, plataformas e fluxo de dados
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Arquitetura completa do Hermes Agent — credenciais, plataformas e fluxo de dados
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Sistema WhatsApp Bot completo — dual-mode (assistente pessoal + suporte a clientes) com histórico de conversas persistence via SQLite
Consulta os logs em tempo real, status e saúde da integração do WhatsApp através do endpoint /whatsapp/debug do bridge.
Realiza o deploy do plugin whatsapp-manager no servidor Hermes — commit, push, pull e restart do container.
Busca em YouTube, web (Brave Search) e Reddit — sem dependências externas, tudo via urllib.
Autoriza acesso ao Gmail via OAuth2 — gera a URL de login para o usuário clicar e salva o token de acesso.
| name | hermes-architecture |
| description | Arquitetura completa do Hermes Agent — credenciais, plataformas e fluxo de dados |
| category | devops |
📌 Fonte de verdade — Este é o documento completo de referência. Contém tudo: arquitetura, credenciais, fluxos, troubleshooting, patches e STT.
Skills relacionadas:
whatsapp-bot-env-vars — operação WhatsApp (dual-mode, startup, DB, SQLite)messaging-gateway-customization — customização avançada (plugins, patching, pitfalls)Guia completo de referência sobre como o sistema funciona: onde estão as credenciais, como cada plataforma se conecta, e como a informação flui entre os componentes.
┌─────────────────────────────────────────────────────────────┐
│ PORTINGER │
│ (Variáveis de Ambiente) │
└──────────┬──────────────┬──────────────────┬────────────────┘
│ │ │
┌──────▼──────┐ ┌────▼────────┐ ┌───────▼──────────┐
│ WhatsApp │ │ E-mail │ │ LLM (MiniMax) │
│ (Baileys) │ │ (Gmail API) │ │ (auth.json) │
└─────────────┘ └─────────────┘ └───────────────────┘
Localização: Variáveis de ambiente no Portainer (não em arquivos)
Variáveis esperadas:
WHATSAPP_ENABLED=true
WHATSAPP_OWNER_NUMBER=5586981612061
WHATSAPP_MODE=mixed
WHATSAPP_BRIDGE_PORT=18732
Onde são usadas:
/opt/data/.hermes/platforms/whatsapp/bridge/bridge.js/opt/data/.hermes/plugins/whatsapp-manager/__init__.py (instalado/atualizado pelo Dashboard do Hermes)/opt/data/.hermes/platforms/whatsapp/session/)/opt/data/.hermes/platforms/whatsapp/bridge.logImportante: O bridge.js está em /opt/data/.hermes/ (persistente), NÃO em /opt/hermes/scripts/ (efêmero). O bridge sobrevive a rebuilds do container porque foi instalado/copiado para o volume persistente.
Verificação:
python3 -c "import os; [print(k,'=',v) for k,v in os.environ.items() if 'WHATSAPP' in k.upper()]"
ps aux | grep bridge | grep -v grep
ATENÇÃO: O sistema de email NÃO usa IMAP/SMTP. Usa a Google Gmail API via OAuth2.
Localização: Variáveis de ambiente no Portainer
Variáveis esperadas:
GOOGLE_CLIENT_ID=206771399571-xxx.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxx
Onde são usadas:
/opt/data/.hermes/scripts/support_agent.py/opt/data/.hermes/skills/productivity/google-workspace/scripts/google_api.pyArquitetura do sistema de email:
Gmail API (Google Workspace OAuth2)
│
▼
support_agent.py ◄── support_rules.md (regras de negócio)
│ └── SOUL_EMAIL.md (persona)
│
▼
MiniMax LLM ◄── auth.json (credenciais do MiniMax)
│
▼
Resposta por email (thread-safe)
Verificação:
python3 -c "import os; [print(k,'=',v[:30]+'...') for k,v in os.environ.items() if 'GOOGLE' in k.upper() or 'CLIENT' in k.upper()]"
Como funciona:
support_agent.py periodicamente (watchdog pattern)GOOGLE_CLIENT_ID e GOOGLE_CLIENT_SECRETsupport_rules.md + SOUL_EMAIL.md → chama MiniMax via API → envia respostaComo rodar manualmente:
cd /opt/data && PYTHONPATH=/opt/hermes/.venv/lib/python3.13/site-packages python3 .hermes/scripts/support_agent.py
Nota: python-dotenv só existe no venv do Hermes (/opt/hermes/.venv), não no Python global do container.
Localização: auth.json no gateway
Arquivo: /opt/data/.hermes/auth.json
Estrutura:
{
"credential_pool": {
"minimax": [
{
"access_token": "eyJ...",
"base_url": "https://api.minimax.io/anthropic",
"scope": "full"
}
]
}
}
Como é usado:
No gateway (Hermes Agent):
/opt/hermes/gateway/auxiliary_client.pyresolve_provider_client("minimax")credential_pool para fazer chamadas APINo support_agent.py (email):
auth.json diretamenteaccess_token e base_url do credential_pool.minimax[0]/v1/messagesVerificação:
cat /opt/data/.hermes/auth.json | python3 -c "import json,sys; d=json.load(sys.stdin); cp=d.get('credential_pool',{}); [print(k,':', list(cp[k].keys()) if isinstance(cp[k],dict) else '***') for k in cp.keys()])"
Arquivo: /opt/data/support_rules.md
O que contém:
Carregado por: support_agent.py
Arquivo: /opt/data/.hermes/profiles/email/SOUL.md
O que contém:
Importante: A persona deve declarar "equipe de suporte" (não "assistente de IA" nem "próprio André"). Gramática sempre em 1ª pessoa plural (nós), nunca 3ª pessoa (ele/ela).
Arquivo: /opt/data/.hermes/profiles/whatsapp/SOUL.md
O que contém:
1. Cron job executa support_agent.py (a cada X minutos)
2. support_agent.py conecta na Gmail API (OAuth2 via GOOGLE_CLIENT_*)
3. Busca emails não lidos: label:INBOX newer_than:1d
4. Para cada email:
a. Verifica se é auto-resposta (loop protection)
b. Verifica se já foi respondido por nós
c. Verifica se humano já participou da thread
d. Verifica se é email promocional/transacional
e. Se tudo ok: chama MiniMax com system_prompt (support_rules.md + SOUL_EMAIL.md)
5. MiniMax retorna resposta em 1ª pessoa plural
6. support_agent.py envia resposta via Gmail API (thread-safe, In-Reply-To)
7. Marca email original como lido (remove UNREAD)
8. Se não houver emails processados: saída silenciosa (watchdog pattern)
1. Usuario envia mensagem no WhatsApp
2. Bridge Node.js (/opt/data/.hermes/platforms/whatsapp/bridge/bridge.js) recebe
3. Bridge faz polling no WhatsApp via Baileys
4. Mensagem enviada ao gateway Hermes
5. Gateway carrega SOUL_whatsapp.md (persona do André, 1ª pessoa singular)
6. MiniMax processa e retorna resposta
7. Gateway envia via bridge → WhatsApp
1. Necessidade de chamada LLM
2. Gateway busca credenciais em auth.json (credential_pool.minimax)
3. auxiliary_client.py monta request com access_token + base_url
4. Endpoint: https://api.minimax.io/anthropic/v1/messages
5. Modelo: MiniMax-M2.7
6. Resposta retorna para o gateway
O arquivo /opt/hermes/agent/auxiliary_client.py é efêmero — todo rebuild do container o sobrescreve. Os patches abaixo precisam ser re-aplicados após cada rebuild manual via Portainer.
minimax a _PROVIDERS_WITHOUT_VISION# Linha ~303 de /opt/hermes/agent/auxiliary_client.py
_PROVIDERS_WITHOUT_VISION: frozenset = frozenset({
"kimi-coding",
"kimi-coding-cn",
"minimax", # ← ADICIONAR
})
gemini como fallback de visão# _VISION_AUTO_PROVIDER_ORDER (linha ~3389):
_VISION_AUTO_PROVIDER_ORDER = (
"openrouter",
"gemini", # ← ADICIONAR
"nous",
)
# _resolve_strict_vision_backend (linha ~3420, antes do return None):
if provider == "gemini":
return resolve_provider_client("gemini", model, is_vision=True)
Após os patches, o fallback de visão fica: minimax → openrouter → gemini (via google/gemini-3-flash-preview).
Verificação pós-rebuild:
grep '"minimax"' /opt/hermes/agent/auxiliary_client.py | grep "_PROVIDERS_WITHOUT_VISION" || echo "PATCH MISSING"
grep '"gemini"' /opt/hermes/agent/auxiliary_client.py | grep "_VISION_AUTO_PROVIDER_ORDER" || echo "PATCH MISSING"
O plugin whatsapp-manager agora transcreve áudios e descreve imagens de forma nativa e integrada usando o Google Gemini API (gemini-3.5-flash), sem necessidade de chaves extras ou patch do core.
ptt ou audio) chega, o plugin codifica o arquivo temporário em base64, envia para a API do Gemini pedindo a transcrição literal, atualiza o evento em tempo real no gateway para [Áudio: "transcrição..."] e atualiza a mensagem no banco de dados SQLite whatsapp_messages.db.[Imagem: descrição...].Caso queira usar a transcrição nativa antiga do core via run.py para outros fluxos:
groq (grátis), openai (pago), local, mistral, xai.GROQ_API_KEY ao credential_pool em auth.json e mudar stt.provider: groq em config.yaml.| Variável | Plataforma | Onde usar | Formato |
|---|---|---|---|
WHATSAPP_ENABLED | Bridge Baileys | true | |
WHATSAPP_OWNER_NUMBER | Bridge Baileys | 5586981612061 | |
WHATSAPP_MODE | Bridge Baileys | mixed | |
GOOGLE_CLIENT_ID | Email + Gemini STT | Gmail API + Gemini | ID do OAuth2 web client |
GOOGLE_CLIENT_SECRET | Email + Gemini STT | Gmail API + Gemini | Secret do OAuth2 |
MINIMAX_API_KEY | LLM (via auth.json) | auth.json, não env var | Token Bearer |
# Todas as variáveis do sistema
python3 -c "import os; print(sorted([k for k in os.environ.keys() if any(x in k for x in ['WHATSAPP','EMAIL','IMAP','SMTP','GOOGLE','CLIENT','MINIMAX'])]))"
# WhatsApp
ps aux | grep bridge | grep -v grep
# Email (ver se support_agent.py está rodando)
cat /opt/data/support_agent.log 2>/dev/null | tail -20
# LLM (ver se auth.json existe)
cat /opt/data/.hermes/auth.json | python3 -c "import json,sys; d=json.load(sys.stdin); [print(k) for k in d.get('credential_pool',{}).keys()])"
| Tipo | Localização |
|---|---|
| Sessão WhatsApp | /opt/data/.hermes/platforms/whatsapp/session/ |
| Bridge WhatsApp | /opt/data/.hermes/platforms/whatsapp/bridge/bridge.js |
| Logs WhatsApp | /opt/data/.hermes/platforms/whatsapp/bridge.log |
| Plugin WhatsApp Manager | /opt/data/.hermes/plugins/whatsapp-manager/__init__.py |
| SQLite histórico | /opt/data/.hermes/whatsapp_messages.db |
| Auth do Gateway | /opt/data/.hermes/auth.json |
| Config do Gateway | /opt/data/.hermes/config.yaml |
| Regras de Suporte | /opt/data/support_rules.md |
| Persona Email | /opt/data/.hermes/profiles/email/SOUL.md |
| Persona WhatsApp | /opt/data/.hermes/profiles/whatsapp/SOUL.md |
| Script email | /opt/data/.hermes/scripts/support_agent.py |
| Google API | /opt/data/.hermes/skills/productivity/google-workspace/scripts/google_api.py |
| Logs Email | /opt/data/support_agent.log |
| Memória persistente | /opt/data/.hermes/memory/MEMORY.md |
Caminhos Efêmeros (wipados em rebuild):
/opt/hermes/ — código fonte do Hermes (sobrescrito em rebuild)/opt/hermes/agent/auxiliary_client.py — patches de visão precisam ser re-aplicados/tmp, /root, /home/hermessupport_agent.py linha ~113: o prefixo do system prompt dizia "Você é um assistente de suporte" (genérico), não "Você é a equipe de suporte do André Alencar respondendo por e-mail"support_agent.py parsing: MiniMax devolve blocks na ordem thinking PRIMEIRO, text DEPOIS. O código antigo pegava block[0] (sempre thinking = raciocínio interno), não a resposta real."Você é a equipe de suporte do André Alencar respondendo por e-mail. Ignore..."text sobre thinkingfor block in content:
if block.get("type") == "text":
return block.get("text", "")
for block in content:
if block.get("type") == "thinking":
return block.get("thinking", "") # fallback
/opt/data/.hermes/scripts/support_agent.pygrep "Enviando resposta" /opt/data/support_agent.log — se aparecer 2x para mesmo msg_id, é este bug/opt/data/.hermes/scripts/support_agent.py/opt/data/.hermes/profiles/whatsapp/SOUL.md_PROVIDERS_WITHOUT_VISION deve incluir "minimax" (já corrigido)git remote set-url origin https://github.com/... (sem token), o push falha com Authentication failedremote: Invalid username or token ao fazer git pushgit remote set-url origin https://TOKEN@github.com/user/repo.git
git push origin main
# Imediatamente depois:
git remote set-url origin https://github.com/user/repo.git
.git-credentials local)ModuleNotFoundError: No module named 'dotenv'python-dotenv só existe no venv do Hermes (/opt/hermes/.venv), não no Python global do containerPYTHONPATH=/opt/hermes/.venv/lib/python3.13/site-packages python3 /opt/data/.hermes/scripts/support_agent.py
/opt/data/.hermes/scripts/support_agent.py