Files
Bundle OKF 0.2 · 7 conceitos · acoalex/haap
Open source Repository Open in the app JSON README (API)
About
# Files
- [HAAP Code Wiki — Orientation and Routing Map](quickstart.md) - Entry point and routing map of the HAAP code wiki: what HAAP is (open pure-Python agent protocol, Python 3.10+, stdlib http.server, no web framework, Ed25519 identity), the alliance and marketplace trust modes, quick-start commands for identity, server, friends, directory and tests, and a goal-oriented map to every wiki page for architecture, protocol concepts, workflows, operations, integrations and testing.
# Directories
- [architecture](architecture/)
- [concepts](concepts/)
- [integrations](integrations/)
- [operations](operations/)
- [testing](testing/)
- [workflows](workflows/)
Details
- Kind
- OKF bundles
- Topic
- Files & documents
- Publisher
- acoalex
- Origin
- okf_github
- Category
- dados
- Version
- 0.2
- Last push
- 2026-09-08T13:11:44Z
- Repository state
- ativo
- Language
- Python
- License
- MIT
- Added
- 2026-09-08 09:02:43
- Updated
- 2026-09-08 09:02:43
- Origin id
acoalex/haap:openwiki/index.md
README
# HAAP — Hermes Agent Alliance Protocol
**Protocolo abierto para que agentes Hermes autónomos de distintas máquinas se descubran, verifiquen su identidad, negocien permisos y trabajen juntos.**
> 🇬🇧 This README is also available in [English](README.en.md).
## La idea
Un agente personal en tu VPS pide *"resérvame peluquería el jueves a las 17:00"*. Una peluquería del otro lado ejecuta su propio agente Hermes con acceso a su calendario de citas. Los dos agentes se descubren, verifican identidad criptográficamente, negocian el permiso de reserva y completan la cita — **sin intervención humana en ninguna de las dos puntas**.
## Instalación como plugin de Hermes Agent (recomendado)
HAAP se instala como **plugin nativo de Hermes**: un comando, y el agente
obtiene las tools `haap_*`, el servidor de mensajería HAAP corriendo **dentro
del gateway**, el registro automático en el directorio público con heartbeats,
y las solicitudes de amistad entregadas en tu chat con los comandos de
aprobación listos para copiar. No hace falta `haap serve`, ni un servicio
systemd aparte, ni pegar código Python.
```bash
# 1. Instala haap dentro del venv de Hermes (Hermes usa su propio entorno uv)
uv pip install git+https://github.com/acoalex/haap.git
# …o como directorio de plugin directamente desde GitHub:
hermes plugins install acoalex/haap --enable
# 2. Activa el plugin (si no usaste --enable)
hermes plugins enable hermes-haap
```
Configuración en `~/.hermes/config.yaml` (todo opcional; también acepta
variables de entorno `HAAP_HERMES_<CLAVE>`):
```yaml
plugins:
enabled: [hermes-haap]
entries:
hermes-haap:
endpoint: "https://tu-agente.com:8443/haap/messages" # URL pública de mensajería
speciality: "asistente-personal"
port: 8443 # puerto del servidor HAAP dentro del gateway
directory_url: "https://acoalex.com/haap-directory"
auto_register: true # regístrate en el directorio al arrancar
heartbeat_interval_s: 21600
```
Al arrancar el gateway (`hermes gateway`), el plugin crea la identidad en
`~/.haap` si no existe, levanta el servidor HAAP, se registra en el directorio y
mantiene la entrada viva. Lo que obtiene tu agente:
| Superficie | Qué hace |
|---|---|
| Tools `haap_whoami`, `haap_registry_search`, `haap_service_search/book`, `haap_delegate_task`, `haap_friends`, `haap_add_friend`, `haap_registry_register` | El modelo usa HAAP como cualquier otra tool |
| Solicitud de amistad entrante | Tarjeta en tu chat de Hermes con `haap friends approve <fp> --role …` listo para copiar |
| `/haap status|friends|requests|search <capacidad>` | Comando rápido en el chat |
| `hermes haap init|whoami|friends|registry …` | La CLI de haap bajo `hermes` |
| Skill `haap` | Guía de uso de las tools para el modelo |
Sigue necesitando ser alcanzable desde fuera: abre el puerto del servidor HAAP
(o ponlo tras tu reverse proxy / túnel) igual que harías con cualquier
servicio. El gateway ya se instala como servicio con `hermes gateway install`.
### Avisos de solicitudes por webhook de Hermes (sin plugin)
Si no usas el plugin (o quieres un segundo canal), `WebhookNotifier` firma en el
**formato genérico V2 de Hermes** (`X-Webhook-Signature-V2` + `X-Webhook-Timestamp`,
HMAC-SHA256 de `<timestamp>.<body>`, anti-replay ±300 s). Una ruta con
`deliver_only: true` entrega la tarjeta en Telegram/Discord/Matrix **sin gastar tokens**:
```yaml
# ~/.hermes/config.yaml
platforms:
webhook:
enabled: true
extra:
port: 8644
routes:
haap-friend-request:
secret: "cambia-este-secreto"
deliver: "telegram" # discord | matrix | slack | …
deliver_only: true # entrega literal, sin invocar al modelo
prompt: |
🤝 Solicitud de amistad HAAP de {name} [{fingerprint}]
mensaje: {message}
aprobar: {how_to_approve}
denegar: {how_to_deny}
```
```python
from haap.policy import WebhookNotifier
server.notifier = WebhookNotifier("http://127.0.0.1:8644/webhooks/haap-friend-request",
"cambia-este-secreto") # fmt="legacy" para el header antiguo
```
Con el plugin basta con `webhook_url` / `webhook_secret` en `plugins.entries.hermes-haap`.
### HAAP como servidor MCP (Hermes, Claude Code, Cursor…)
Las mismas tools `haap_*` se exponen también por **MCP (stdio)** con `haap mcp`,
para usarlas desde cualquier host MCP —o desde un Hermes donde prefieras MCP a plugin:
```yaml
# Hermes: ~/.hermes/config.yaml → tools mcp__haap__haap_whoami, mcp__haap__haap_registry_search…
mcp_servers:
haap:
command: "haap"
args: ["mcp"] # añade --serve --endpoint https://… para correr también el servidor HAAP
```
```json
// Claude Code: .mcp.json
{ "mcpServers": { "haap": { "command": "haap", "args": ["mcp"] } } }
```
`haap mcp` comparte identidad y estado (`~/.haap`) con la CLI y el plugin: son tres
puertas al mismo agente.
## Instalación manual (librería + servidor aparte)
Si prefieres no usar el plugin —o no usas Hermes— puedes usar haap como
librería y servidor independientes:
Requisitos: Python 3.10+, un Hermes Agent funcionando (cualquier máquina con acceso a red).
### 1. Instalar el paquete
```bash
# En el VPS/ordenador donde corre tu Hermes
git clone https://github.com/acoalex/haap.git
cd haap
pip install -e .
```
Esto instala el comando `haap` y la librería `haap` en tu Python. Para verificar:
```bash
haap --version
```
### 2. Crear la identidad de tu agente
```bash
haap init --name "Agente Personal de Alex" --endpoint "https://tu-vps.com:8443/haap/messages"
haap whoami
```
- `--endpoint` es la URL pública donde tu agente recibirá mensajes (puede añadirla después). Si tu VPS solo es alcanzable tras un túnel o solo inicias tú las conexiones, puedes omitirla.
- La identidad (par de claves Ed25519) se guarda en `~/.haap/identity.json` con permisos `0600`. **Nunca la compartas ni la subas a ningún repo.**
### 3. Exponer el servidor HAAP en tu Hermes
La forma más simple: correr el servidor HAAP como servicio junto a tu gateway de Hermes:
```bash
# en primer plano (para probar):
haap serve --port 8443 --speciality "asistente-personal"
# como servicio systemd persistente:
sudo tee /etc/systemd/system/haap.service > /dev/null <<'EOF'
[Unit]
Description=HAAP messaging server
After=network-online.target
[Service]
User=TU_USUARIO
ExecStart=/usr/local/bin/haap serve --port 8443
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now haap
```
El servidor expone:
| Endpoint | Uso |
|---|---|
| `POST /haap/messages` | entrada de envelopes firmados (handshake, tareas, marketplace) |
| `GET /.well-known/haap.json` | tu manifest público (sin claves) |
| `GET /health` | comprobación de vida |
Asegúrate de abrir el puerto en el firewall (`sudo ufw allow 8443/tcp`) y, si usas HTTPS, pon el servidor detrás de un reverse proxy (Caddy/nginx) o un túnel (cloudflared).
### 4. Usarlo desde tu agente Hermes (Python)
Desde cualquier tool de ejecución Python de tu Hermes (o un skill propio):
```python
import sys
sys.path.insert(0, "/ruta/a/haap") # o pip install -e . y no hace falta
from haap.identity import IdentityStore
from haap.directory import Directory
from haap.client import HAAPClient
from haap.transport import HttpTransport
identity = IdentityStore().load() # tu identidad (~/.haap)
directory = Directory() # tus amigos (~/.haap/friends.json)
client = HAAPClient(identity, directory,
transport=HttpTransport())
# ── Delegar una tarea a un agente amigo (alliance) ──
resultado = client.delegate_task(
"HF-xxxxxxxxxxxxxxxx", # fingerprint del amigo
"Resúmeme el informe trimestral del repo X",
action="task:submit",
)
print(resultado)
# ── Reservar en un negocio publicado (marketplace, sin amistad previa) ──
disponibilidad = client.service_search(
"HF-yyyyyyyyyyyyyyyy", # fingerprint de la peluquería
"https://peluqueria.com:8443", # endpoint base de su agente
services="corte", date="2026-09-10",
)
cita = client.service_book(
"HF-yyyyyyyyyyyyyyyy",
"https://peluqueria.com:8443",
service="corte", when="2026-09-10T17:00",
)
print(cita) # {'estado': 'reservada', 'cita': '2026-09-10 17:00', ...}
```
### 5. Registrar tu agente en un directorio (para que otros te descubran)
El directorio público de referencia está **operativo**:
**https://acoalex.com/haap-directory** (código y SPEC en
[acoalex/haap-directory](https://github.com/acoalex/haap-directory)).
```bash
# registrarte en el directorio público (flujo proof-of-endpoint automático):
haap registry register --registry https://acoalex.com/haap-directory \
--endpoint https://tu-agente.com:8443/haap/messages \
--speciality tu-especialidad
# descubrir agentes por capacidad:
haap registry search --registry https://acoalex.com/haap-directory \
--capability citas-peluqueria
# levantar tu propio directorio (opcional, para tu comunidad/sector):
haap registry serve --port 8444
# (para producción usa el servicio independiente `haap-dird`:
# https://github.com/acoalex/haap-directory)
```
Las entradas expiran a los 7 días si no se renuevan; mantén la tuya viva con
un `HeartbeatLoop` (hilo demonio que heartbeat-a cada 6 h):
```python
from haap.registry_client import HeartbeatLoop
HeartbeatLoop("https://acoalex.com/haap-directory",
identity.fingerprint).start()
```
## Cómo hacer "amigos" (modo alliance)
1. **Tú inicias** (conoces el fingerprint y endpoint del otro agente):
```bash
haap friends add HF-83b91c82c444f558 \
--public-key "<su clave pública base64>" \
--name "Agente de Mi Socio" \
--endpoint "https://su-vps.com:8443/haap/messages"
```
y desde Python: `client.start_friendship(...)` — el otro lado recibe el `friend_request`.
2. **El otro dueño aprueba con un rol** (nunca se hace solo):
```bash
haap friends requests # ve la cola de solicitudes pendientes
haap friends approve HF-xxxx... --role partner
```
3. **A partir de ahí**: tareas delegadas con permisos acotados por el rol, rate limits y auditoría en ambos lados.
Si el otro agente te envía a ti la solicitud, el flujo es el mismo pero en sentido inverso: tú ves `pending_in` y decides con `approve`/`deny`.
## Gestión de solicitudes de amistad: roles, política y notificaciones
Cuando un agente desconocido envía una solicitud de amistad, HAAP la evalúa automáticamente contra tu **política** (`~/.haap/policy.json`) con tres resultados posibles, en este orden:
```
friend_request entrante (firmado)
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
DENY AUTO-APPROVE QUEUE
(blocklist o (regla por fingerprint (default: se guarda
default=deny) o especialidad, capado pending_in y se
│ por max_role) NOTIFICA al dueño)
▼ ▼ ▼
rechazo friend_accept tarjeta accionable en tu
inmediato con matriz granted chat / cola de pendientes
```
### Roles de permisos
En lugar de componer matrices JSON a mano, apruebas con una plantilla con nombre:
```bash
haap friends roles # lista los roles disponibles y sus permisos
haap friends requests # solicitudes pendientes + comando de decisión sugerido
haap friends approve HF-xxxx... --role client
haap friends approve HF-xxxx... --role partner
```
| Rol | Qué puede hacer el otro agente |
|---|---|
| `guest` | Solo conversación/ping. Sin tareas. |
| `client` | Scopes de reserva (`booking:*`, `service:*`). Ideal para clientes de marketplace. |
| `partner` | Delegación de tareas amplia + lecturas de agenda/calendario. |
| `family` | Como partner, con rate limits altos (agentes personales de confianza). |
| `admin` | Todo, incluido `file:write` y `exec:terminal`. **Solo para agentes que controlas al 100%.** |
Puedes definir tus propios roles (y heredar de los integrados) en `~/.haap/roles.json`:
```json
{
"vip": {
"extends": "partner",
"description": "Clientes VIP",
"rate_limits": {"*": {"capacity": 500, "refill_per_sec": 5.0}}
}
}
```
### Política de solicitudes (`~/.haap/policy.json`)
```json
{
"default": "queue",
"auto_approve": [
{"fingerprint": "HF-3f7a9c1b2d4e5f60", "role": "partner"},
{"speciality": "citas-peluqueria", "role": "client"}
],
"max_role": "partner"
}
```
- `"default": "queue"` (recomendado) — todo lo que no encaje en reglas queda pendiente de tu aprobación
- `"default": "deny"` — modo cerrado: solo entran los que coincidan con una regla de `auto_approve`
- **`max_role` acota el auto-approve**: aunque una regla pida `admin`, nunca se auto-concederá más que tu rol tope (un rol desconocido se auto-capar a `client`)
### Notificaciones accionables
La solicitud en cola genera una **tarjeta** con todo lo que necesitas para decidir:
```
=== HAAP FRIEND REQUEST (pending your approval) ===
from: HF-3f7a9c1b2d4e5f60
name: Agente de Ana
message: Hola, soy el asistente de Ana
wants: role 'admin' → would grant 'client'
decide: haap friends approve HF-3f7a9c1b2d4e5f60 --role client
======================================================
```
Mecanismos de notificación (combinables):
- **ConsoleNotifier** (default) — imprime la tarjeta en los logs del servicio
- **WebhookNotifier** — POST firmado con HMAC-SHA256 hacia tu Hermes (webhook → tu chat de Matrix/Telegram): apruebas desde el móvil copiando el comando
- **CompositeNotifier** — varios a la vez
```python
from haap.policy import WebhookNotifier, ConsoleNotifier, CompositeNotifier
from haap.server import HAAPServer
server = HAAPServer(ident, directory,
notifier=CompositeNotifier(
ConsoleNotifier(),
WebhookNotifier("https://tu-hermes.com/webhooks/haap-friends",
secret="secreto-compartido-con-hermes"),
))
```
El `friend_accept` que recibe el otro agente incluye la **matriz concedida real** (`granted` + `granted_role`): si pidió `admin` y concediste `client`, su agente sabe exactamente qué puede hacer — la contraoferta es transparente, no un silencio ambiguo.
## Cómo publicar servicios (modo marketplace, para negocios)
Un negocio (peluquería, taller, clínica…) publica reservas abiertas:
```python
from haap.identity import IdentityStore
from haap.directory import Directory
from haap.server import HAAPServer
ident = IdentityStore().load()
server = HAAPServer(
ident, Directory(),
speciality="citas-peluqueria",
marketplace_catalog={
"corte": {"price_eur": 15, "duration_min": 30},
"corte+barba": {"price_eur": 22, "duration_min": 45},
},
marketplace_policy={"auto_accept": True, "open_hours": "10:00-19:00"},
# aquí es donde el negocio conecta SU calendario real (CalDAV, Google
# Calendar, su software de citas...): el callback recibe la reserva:
on_task=lambda task_id, payload: mi_calendario.reservar(payload),
)
server.start(host="0.0.0.0", port=8443)
```
Cualquier agente del mundo puede entonces buscar y reservar **sin amistad previa**: su petición llega firmada criptográficamente, se audita, se rate-limita y puede bloquearse al instante (`haap friends block HF-...`).
## Demo funcionando
```bash
python3 demo_marketplace.py
```
Levanta dos agentes reales sobre HTTP (peluquería + agente personal), reserva una cita y muestra el calendario del negocio y la auditoría de ambos lados. Es el flujo completo del caso de uso: **cero intervención humana**.
## Componentes
| Componente | Estado | Descripción |
|---|---|---|
| `haap/crypto.py` | ✅ | Ed25519 (firma/verificación), claves en bruto, base64 |
| `haap/identity.py` | ✅ | Par de claves persistente + fingerprint `HF-<16 hex>` |
| `haap/envelope.py` | ✅ | Envelope JSON canónico firmado, timestamp ±300 s, nonce anti-replay |
| `haap/permissions.py` | ✅ | Permisos granulares deny-by-default por agente amigo |
| `haap/rate_limiter.py` | ✅ | Token bucket por (amigo, acción) |
| `haap/audit.py` | ✅ | Registro de auditoría append-only |
| `haap/directory.py` | ✅ | Registro local de amigos: pending/accepted/blocked |
| `haap/capabilities.py` | ✅ | Manifest de capacidades del agente |
| `haap/tasks.py` | ✅ | Ciclo de vida de tareas estilo A2A |
| `haap/transport.py` | ✅ | Memory/HTTP transports sobre el envelope |
| `haap/server.py` | ✅ | Servidor de mensajería: handshake, autorización, well-known |
| `haap/client.py` | ✅ | Cliente: amistad, delegación de tareas, marketplace |
| `haap/registry.py` | ✅ | Directorio público federado (proof-of-endpoint + heartbeats) |
| `haap/registry_client.py` | ✅ | Cliente de directorio (register/search/heartbeat) |
| `haap/roles.py` | ✅ | Plantillas de permisos: guest/client/partner/family/admin |
| `haap/policy.py` | ✅ | Motor de solicitudes (deny/auto-approve/queue) + notificadores |
| `haap/cli.py` | ✅ | Comando `haap` (init/whoami/friends/task/serve/registry/mcp) |
| `haap/tools.py` | ✅ | Superficie de tools `haap_*` compartida (runtime, schemas, handlers) para plugin y MCP |
| `haap/hermes_plugin/` | ✅ | Plugin nativo de Hermes Agent: tools, servidor en el gateway, registro/heartbeat, avisos en el chat, `/haap`, skill |
| `haap/mcp_server.py` | ✅ | Servidor MCP (stdio JSON-RPC) con las mismas tools; CLI `haap mcp` |
| Tests (63) | ✅ | Handshake completo, autorización, abuso, marketplace, directorio, plugin de Hermes, webhook V2, MCP |
## Principios de seguridad
1. **La identidad vive en las claves, no en ningún servicio.** Fingerprint = SHA-256 de la clave pública Ed25519. Un directorio no puede suplantar a nadie.
2. **Aprobación humana obligatoria** para amistades entre agentes (alliance mode).
3. **Deny-by-default** en todos los permisos; scopes granulares (`task:submit`, `read:calendar`, `booking:reserve`…).
4. **Anti-replay**: nonces por emisor + ventana de timestamp ±300 s + firma sobre JSON canónico determinista (floats prohibidos).
5. **Verificación autocontenida en bootstrap**: los mensajes iniciales llevan la clave pública del emisor y se comprueba `fingerprint == SHA-256(clave)` — un impostor con clave falsa es rechazado.
6. **Proof-of-Endpoint** en el directorio: no se lista un agente sin demostrar control firmado del endpoint declarado.
7. **Auditoría append-only** de todo mensaje aceptado o rechazado.
8. **Denial-of-wallet acotado**: rate limits por amigo y por acción.
## Dos modos de confianza
- **Alliance** — amistad mutua verificada (challenge-response + aprobación humana). Para pares recurrentes de confianza: tus propios VPS, familia, socios.
- **Marketplace** — negocios que publican servicios de reserva abiertos (`service_search/quote/book/cancel`), con identidad firmada del cliente, auditoría y blacklist. Sin amistad previa.
## Estado y roadmap
Core + marketplace + **política de amistades con roles** funcionales y probados (63 tests), más el **plugin nativo de Hermes** (`haap.hermes_plugin`): tools, servidor en el gateway, registro/heartbeat automáticos y avisos de solicitudes en el chat del dueño; `WebhookNotifier` en formato V2 de Hermes; y servidor **MCP** (`haap mcp`) con las mismas tools. Pendiente en el roadmap: verificación de negocio por dominio web y reputación federada (ya disponibles en el directorio [haap-directory](https://github.com/acoalex/haap-directory), falta consumirlas desde el cliente). Ver [ARQUITECTURA.md](docs/ARQUITECTURA.md) para el diseño completo: threat model (10 amenazas), diagramas de secuencia, gobernanza de directorios federados y compatibilidad con el estándar A2A.
## Licencia
MIT