feat(hermes): ADR-018 Hermes Agent (Nous Research) integration Phase 1 - #63
Open
UNIFY-MC wants to merge 4 commits into
Open
feat(hermes): ADR-018 Hermes Agent (Nous Research) integration Phase 1#63UNIFY-MC wants to merge 4 commits into
UNIFY-MC wants to merge 4 commits into
Conversation
Documenta integração formal do Hermes Agent (self-hosted Nous Research v0.14.0)
como executivo externo do Mário, complementar aos CookAI agents internos.
Status: Draft (aguarda 4 decisões finais Mário)
- D2 ✅ Confirmado: VPS Ubuntu Hetzner CAX11 (~€3.79/mês) + Anthropic API direct
- D3 confirma via Discord Developer Portal (bot Hermes separado de property007)
- D4 [PENDING]: memory model interno (built-in v0.14.0 / Letta / Mem0 / pgvector / a descobrir)
- D6 [PENDING]: split detalhado 20 tarefas Hermes vs CookAI agents tabulado
Decisões CONFIRMADAS:
D1 — Hermes externo ao monorepo (não copiar para apps/)
D2 — Hetzner CAX11 ARM EU recomendado (~€10-25/mês total Hermes operacional)
D5 — Hermes invoca CookAI via Edge Function 'hermes-invoke-recipe' com:
* system.api_keys row 'hermes_executor' + iam.permission_grants whitelist
* 7 RPCs whitelisted (get_record_summary, list_records, search_records,
get_activity_timeline, create_task, queue_approval, ask_property007_intent)
D7 — 5 padrões canónicos agente↔Hermes:
1) Hermes orquestra → CookAI executa
2) CookAI escala → Hermes notifica Mário (Discord)
3) Hermes detecta padrão → propõe nova skill CookAI
4) Hermes faz Truth Engine query → consume swarm_discoveries
5) Hermes acede activity_unified para context cross-vertical
D8 — Bia deprecada (ARCH-002 brownfield); Mia mantém papel especializado V5
Custos totais estimados Hermes operacional: ~€10-25/mês
(vs €500-2000/mês de managed agents enterprise — savings dramáticos via self-host).
Implementação Phase 1 (próximo commit):
- migration: system.api_keys + iam.permission_grants seed Hermes
- Edge Function: hermes-invoke-recipe (wrapper REST whitelist 7 RPCs)
- smoke test E2E
Refs: ADR-010, ADR-011, ADR-013, ADR-V11-004, ADR-V11-005, ADR-017,
ARCH-002 brownfield, project-hermes-agent-nous memory
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… Phase 1A]
Phase 1 Step A do ADR-018 — infraestrutura para Hermes Agent (Nous Research)
invocar CookAI recipes via Supabase REST API.
ADR-018 update — D5 CORRIGIDO:
Proposta original tinha api_key_id em iam.permission_grants — INCORRECTA.
iam.permission_grants tem PK (group_code, section_code) — não suporta api_key_id.
Solução adoptada (coerente com iam.staff_login_aliases pattern):
system.api_keys.permission_group_code → iam.permission_groups.code
Bridge: RPC iam.api_key_can(p_api_key, p_section, p_action) → boolean
Migration 202605240100_hermes_api_key.sql (486 linhas):
PARTE A — CREATE TABLE system.api_keys (14 colunas, 3 RLS policies staff_only,
3 indexes, trigger updated_at, service_role bypass)
PARTE B — INSERT iam.permission_groups: 'hermes_executor'
PARTE C — INSERT iam.permission_sections (8 rows, idempotente via ON CONFLICT):
system.recipes_exec, system.tasks_create, core.{pessoas,empresas,
imoveis,condominios,activity_unified}_read, system.swarm_discoveries_read
PARTE D — INSERT iam.permission_grants (8 rows whitelist hermes_executor):
recipes_exec + tasks_create can_create=true,
restantes 6 só can_view=true (least-privilege)
PARTE E — CREATE FUNCTION iam.api_key_can(text,text,text):
SECURITY DEFINER, GRANT EXECUTE TO service_role only
Hash bcrypt via pgcrypto crypt() match
PARTE F — INSERT system.api_keys row placeholder:
name='hermes_executor', api_key_hash='\$PENDING\$', active=false
(Mário gera key real via bash script + UPDATE manual após apply)
Idempotente: todos CREATE IF NOT EXISTS + ON CONFLICT DO NOTHING.
Reversível: DROP TABLE + DELETE rows.
RGPD: api_key_hash bcrypt 10 rounds, plaintext nunca persistido.
0 GRANT anon (Regra X).
Phase 1 Step B (próximo commit): Edge Function hermes-invoke-recipe.
Refs: ADR-018, ADR-013 IAM pattern, ARCH-002 Bia→Mia rename relacionado
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…18 Phase 1A]
Fix migration foi aplicada em V1 (hkmvszkpxjbxmnixzqbl) durante apply Phase 1A
porque pgcrypto.crypt() está em schema 'extensions' (não 'public'). RPC iam.api_key_can
falhava silenciosamente sem este fix.
Este commit cria o ficheiro mirror local para evitar DB-003 (215 migrations remotas
sem ficheiro git) brownfield Critical. Source SQL recuperado via
execute_sql FROM supabase_migrations.schema_migrations WHERE name LIKE 'hermes_api_key%'.
Conteúdo:
- CREATE OR REPLACE FUNCTION iam.api_key_can com SET search_path = iam, system, extensions, public
- Qualifica extensions.crypt() explicitamente (defesa em profundidade)
- REVOKE ALL FROM public/anon/authenticated + GRANT EXECUTE TO service_role
Forward-only. Idempotente (CREATE OR REPLACE). Validado em DB:
SELECT iam.api_key_can('any', 'system.recipes_exec', 'create') → false (placeholder).
Refs: ADR-018, DB-003 brownfield, supabase-designer session
Wrapper REST para Hermes Agent (Nous Research) invocar CookAI recipes via API.
Fluxo:
1. POST com x-api-key header + body { recipe_slug | recipe_id, payload, idempotency_key? }
2. Valida via RPC iam.api_key_can('system.recipes_exec', 'create') → 403 se inválida
3. Resolve recipe (slug→id) + valida status='active' → 404/409 se não
4. Idempotência: tasks últimas 24h com tag 'idempotency:<key>' → devolve existing se duplicate
5. Cria system.tasks via RPC system.task_create (kind='task' + tag 'recipe_invoke')
6. Devolve 202 Accepted com { task_id, recipe_slug, status: 'queued', idempotency_key }
Auth: verify_jwt=false (custom via x-api-key).
Pattern D7-1 do ADR-018: Hermes orquestra → CookAI executa.
Audit: cada invocação loga via trigger de system.task_create → core.agent_audit_log.
Constraints respeitadas:
- kind='task' (existing constraint) + tag 'recipe_invoke' para distinção
- TODO Phase 1B+1: expandir tasks_kind_check para incluir 'recipe_invoke'
- 0 GRANT anon (Regra X) — todos os RPCs invocados são SECURITY DEFINER service_role
- CORS configurado mas restritivo
- 5 error codes claros (401/400/403/404/409/500)
Phase 1 Step C (próximo): smoke test E2E.
Refs: ADR-018 D5 + D7-1, ARCH-002 brownfield
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced May 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resumo
5002c41).system.api_keys+iam.permission_groups(hermes_executor) + 8permission_sections+ 8permission_grantswhitelist + RPCiam.api_key_can(api_key_id, section, action)(dd100b5).202605240101sincroniza DB → git (search_path da RPC incluiextensionspara evitar regressão futura) (02aa424).hermes-invoke-recipe— entry point HTTP que validaX-API-Key, resolveapi_key_id, chamaiam.api_key_can()e despacha para a recipe pedida (a8aa8ab).Estado actual em produção
Tudo aplicado em V1 Core Hub (
hkmvszkpxjbxmnixzqbl) em modo seguro:system.api_keys(Hermes row)active = falseiam.permission_groups(hermes_executor)iam.api_key_can()search_path = iam, system, public, extensionshermes-invoke-recipecedcf76e-eb49-4330-a01a-9508617b4c80)verify_jwt = false(auth viaX-API-Key)Como
active = falsee não há hash real, qualquer chamada actual à EF devolve 401/403 — não há risco de execução não autorizada.Pendente para @mario
system.api_keys:Test plan
Validation queries (SQL Editor V1 Core Hub)
search_pathcorrecto:Edge Function smoke test (após gerar key real)
X-API-Key→ 401.X-API-Keyinválido → 401.cookai.recipes/read) → 200.iam.activity_logs(ou equivalente) após chamada bem-sucedida.Gate de merge
apps/).Refs
.claude/strategy/adrs/ADR-018-hermes-agent-integration.md(DRAFT)hermes_executorproject-hermes-agent-nous(contexto Nous Research)supabase/migrations/202605240100_*.sql+202605240101_*.sql(mirror fix)supabase/functions/hermes-invoke-recipe/🤖 Generated with Claude Code