بنقرة واحدة
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