Skip to main content

hermes-agentmesh-async-bus

Build cross-device async multi-agent systems using Redis message bus with 0-SSH deployment

Ir a la instalación

Datos de origen

Repositorio
reason-machines/hermes-skills
Última actividad en el origen
18 de junio de 2026 a las 01:51
Idioma detectado de SKILL.md
inglés
Estrellas
5
Forks
0

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
hermes-agentmesh-async-bus
description
Build cross-device async multi-agent systems using Redis message bus with 0-SSH deployment
triggers
["set up async message bus for multi-agent systems","deploy Hermes AgentMesh across devices","configure Redis-backed agent communication","fix agent timeout issues with async messaging","run cross-device agent collaboration without SSH","build peer-to-peer agent mesh network","orchestrate multi-agent debate asynchronously","troubleshoot AgentMesh worker deployment"]
# Hermes AgentMesh Async Bus > Skill by [ara.so](https://ara.so) — Hermes Skills collection. ## What It Does Hermes-AgentMesh is a **Redis-backed async message bus** that solves HTTP timeout crashes for long-running multi-agent tasks. Instead of synchronous `requests.post()` calls that timeout after 5-10 minutes, agents communicate via Redis queues ("mailboxes") that persist tasks indefinitely. **Key capabilities:** - **0-SSH cross-device deployment** — workers run as systemd/LaunchAgent daemons - **Timeout elimination** — 15-minute+ agent tasks work reliably - **Framework agnostic** — works with Hermes, OpenClaw, LangGraph, AutoGen, CrewAI, custom agents - **Natural persistence** — tasks survive server restarts - **Decoupled architecture** — sender doesn't block waiting for receiver **Architecture:** ``` Mac mini (central hub) Remote nodes (X230i, Pi, WSL) ├── Redis :6379 (0.0.0.0) └── worker_node.py (systemd) ├── Hermes LLM API :8642 └── reads inbox:nodename ├── HTTP file server :8080 └── writes outbox:orchestrator └── worker_macmini (LaunchAgent) ``` ## Installation ### Prerequisites - 1 central machine (Mac mini recommended) running Redis + Hermes Gateway - 1+ remote nodes (Linux/Mac/WSL) on same LAN - Python 3.8+ with `redis`, `requests`, `python-dotenv` ### Step 1: Mac Mini (Central Hub) ```bash # Make Redis accessible across LAN sudo sed -i.bak \ -e 's/^bind 127.0.0.1 ::1$/bind 0.0.0.0/' \ -e 's/^protected-mode yes$/protected-mode no/' \ /opt/homebrew/etc/redis.conf brew services restart redis # Verify cross-device access redis-cli ping # PONG # Install Python dependencies pip3 install redis requests python-dotenv # Clone repository git clone https://github.com/seleman66eeddwegger3-art/hermes-agentmesh.git cd hermes-agentmesh # Create config directory mkdir -p ~/.hermes/async_bus # Configure environment cp .env.example ~/.hermes/async_bus/.env_common nano ~/.hermes/async_bus/.env_common ``` **Edit `.env_common`:** ```bash REDIS_HOST=192.168.1.100 # Your Mac mini LAN IP REDIS_PORT=6379 REDIS_DB=0 REDIS_PROTOCOL=2 # Critical: avoids redis-py 5.x RESP3 bugs API_URL=http://192.168.1.100:8642/chat API_KEY=your_hermes_api_key_from_~/.hermes/.env # Node-specific (override per machine) NODE_NAME=macmini ``` ```bash # Copy worker scripts cp worker_node.py ~/.hermes/async_bus/ cp orchestrator_async.py ~/.hermes/async_bus/ # Install LaunchAgent for persistent worker cp deploy/macos-launchd-worker.plist ~/Library/LaunchAgents/ai.hermes.async_bus_worker.plist sed -i '' 's/<NODE_NAME>/macmini/g' ~/Library/LaunchAgents/ai.hermes.async_bus_worker.plist # Start worker daemon launchctl bootstrap gui/$UID ~/Library/LaunchAgents/ai.hermes.async_bus_worker.plist launchctl kickstart gui/$UID/ai.hermes.async_bus_worker # Verify worker is running launchctl print gui/$UID/ai.hermes.async_bus_worker | grep state # Expected: state = running # Install file server for 0-SSH deployment cp deploy/macos-launchd-serve.plist ~/Library/LaunchAgents/ai.hermes.async_bus_serve.plist launchctl bootstrap gui/$UID ~/Library/LaunchAgents/ai.hermes.async_bus_serve.plist ``` ### Step 2: Remote Nodes (Linux/WSL) ```bash # On remote node (e.g. ubuntu@192.168.1.101) mkdir -p ~/.hermes/async_bus ~/.config/systemd/user # Pull files from Mac mini HTTP server (no SSH/SCP needed) MAC_MINI_IP=192.168.1.100 curl -s http://$MAC_MINI_IP:8080/worker_node.py -o ~/.hermes/async_bus/worker_node.py curl -s http://$MAC_MINI_IP:8080/orchestrator_async.py -o ~/.hermes/async_bus/orchestrator_async.py curl -s http://$MAC_MINI_IP:8080/.env_common -o ~/.hermes/async_bus/.env_common # Override NODE_NAME for this machine echo "NODE_NAME=node99" >> ~/.hermes/async_bus/.env_common # Install systemd unit curl -s http://$MAC_MINI_IP:8080/deploy/linux-systemd-worker.service \ -o ~/.config/systemd/user/async_bus_worker.service sed -i 's/<NODE_NAME>/node99/g' ~/.config/systemd/user/async_bus_worker.service # Enable persistent worker (survives logout) systemctl --user daemon-reload systemctl --user enable --now async_bus_worker # Verify worker systemctl --user status async_bus_worker journalctl --user -u async_bus_worker -f ``` ## Core Concepts ### Message Bus Protocol **4-step async protocol:** 1. **Task push** — Orchestrator pushes to `inbox:<NODE_NAME>` 2. **Worker poll** — Node's worker daemon blocks on `BRPOP inbox:<NODE_NAME>` 3. **LLM execution** — Worker calls Hermes API with task payload 4. **Result return** — Worker pushes to `outbox:orchestrator` **Task JSON format:** ```json { "turn": 1, "node": "node99", "messages": [ {"role": "system", "content": "You are agent 99 in a debate."}, {"role": "user", "content": "What's your position on topic X?"} ] } ``` ### Mailbox Naming Convention ```python inbox:<NODE_NAME> # Where orchestrator sends tasks TO this node outbox:orchestrator # Where all nodes send results BACK to orchestrator ``` ## Key Usage Patterns ### Pattern 1: Run Multi-Agent Debate ```python # orchestrator_async.py - edit configuration TOPIC = "Should AI agents use async messaging over HTTP?" MAX_TURNS = 3 NODES = ["macmini", "node99", "nodepi"] # Run orchestrator (blocks until all turns complete) cd ~/.hermes/async_bus source .env_common python3 orchestrator_async.py ``` **What happens:** 1. Orchestrator pushes tasks to `inbox:macmini`, `inbox:node99`, `inbox:nodepi` 2. Each node's worker daemon picks up task via `BRPOP` 3. Workers call Hermes LLM API (5-15 min per turn) 4. Workers push responses to `outbox:orchestrator` 5. Orchestrator collects results, starts next turn 6. Final report written to `async_debate_<timestamp>.md` ### Pattern 2: Custom Agent Integration **For non-Hermes frameworks (LangGraph, AutoGen, etc.):** ```python import redis import json import os # Connect to shared Redis r = redis.Redis( host=os.getenv("REDIS_HOST"), port=int(os.getenv("REDIS_PORT")), db=int(os.getenv("REDIS_DB")), protocol=2 # CRITICAL: avoid RESP3 bugs ) # Listen for tasks (blocking) def worker_loop(node_name): inbox = f"inbox:{node_name}" while True: # Block until task arrives _, task_raw = r.brpop(inbox, timeout=0) task = json.loads(task_raw) # Execute with your framework result = your_agent_framework.run( messages=task["messages"], context=task.get("context", {}) ) # Return result response = { "turn": task["turn"], "node": node_name, "response": result } r.lpush("outbox:orchestrator", json.dumps(response)) ``` ### Pattern 3: Push Task from Orchestrator ```python import redis import json import os r = redis.Redis( host=os.getenv("REDIS_HOST"), port=int(os.getenv("REDIS_PORT")), db=int(os.getenv("REDIS_DB")), protocol=2 ) def dispatch_task(node_name, turn, messages): task = { "turn": turn, "node": node_name, "messages": messages } inbox = f"inbox:{node_name}" r.lpush(inbox, json.dumps(task)) print(f"✓ Pushed turn {turn} to {inbox}") # Example usage dispatch_task("node99", 1, [ {"role": "system", "content": "You are a code reviewer."}, {"role": "user", "content": "Review this function: def foo(): pass"} ]) ``` ### Pattern 4: Collect Results ```python import redis import json import time r = redis.Redis(host=os.getenv("REDIS_HOST"), protocol=2) def collect_results(expected_count, timeout=600): results = [] start = time.time() while len(results) < expected_count: remaining = timeout - (time.time() - start) if remaining <= 0: break # Block for result (max remaining time) item = r.brpop("outbox:orchestrator", timeout=int(remaining)) if item: _, result_raw = item results.append(json.loads(result_raw)) return results # Collect 3 agent responses responses = collect_results(3, timeout=900) for resp in responses: print(f"{resp['node']}: {resp['response'][:100]}...") ``` ## Configuration ### Environment Variables **Required in `.env_common`:** ```bash # Redis connection REDIS_HOST=192.168.1.100 # Mac mini LAN IP REDIS_PORT=6379 REDIS_DB=0 REDIS_PROTOCOL=2 # MUST be 2 (RESP2) not 3 # Hermes LLM API API_URL=http://192.168.1.100:8642/chat API_KEY=${HERMES_API_KEY} # From ~/.hermes/.env # Node identity (override per machine) NODE_NAME=macmini # Or node99, nodepi, etc. ``` ### LaunchAgent Configuration (macOS) **`~/Library/LaunchAgents/ai.hermes.async_bus_worker.plist`:** ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>ai.hermes.async_bus_worker</string> <key>ProgramArguments</key> <array> <string>/bin/bash</string> <string>-c</string> <string>source ~/.hermes/async_bus/.env_common && exec /usr/local/bin/python3 -u ~/.hermes/async_bus/worker_node.py</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>StandardOutPath</key> <string>/Users/youruser/.hermes/async_bus/worker_macmini.log</string> <key>StandardErrorPath</key> <string>/Users/youruser/.hermes/async_bus/worker_macmini.err</string> </dict> </plist> ``` ### Systemd Configuration (Linux) **`~/.config/systemd/user/async_bus_worker.service`:** ```ini [Unit] Description=Hermes AgentMesh Worker (node99) After=network.target [Service] Type=simple WorkingDirectory=%h/.hermes/async_bus EnvironmentFile=%h/.hermes/async_bus/.env_common ExecStart=/usr/bin/python3 -u %h/.hermes/async_bus/worker_node.py Restart=always RestartSec=10 StandardOutput=append:%h/.hermes/async_bus/worker_node99.log StandardError=append:%h/.hermes/async_bus/worker_node99.err [Install] WantedBy=default.target ``` ## Troubleshooting ### Worker Not Starting ```bash # macOS: Check LaunchAgent status launchctl list | grep async_bus launchctl print gui/$UID/ai.hermes.async_bus_worker # Linux: Check systemd status systemctl --user status async_bus_worker journalctl --user -u async_bus_worker -n 50 # Common fix: Reload after config changes launchctl bootout gui/$UID/ai.hermes.async_bus_worker launchctl bootstrap gui/$UID ~/Library/LaunchAgents/ai.hermes.async_bus_worker.plist ``` ### Redis Connection Refused ```bash # Verify Redis is bound to 0.0.0.0 redis-cli CONFIG GET bind # Expected: 0.0.0.0 # Test from remote node redis-cli -h 192.168.1.100 ping # Expected: PONG # Fix: Edit redis.conf
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub