Skip to main content

hermes-agentmesh-async-bus

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

الانتقال إلى التثبيت

معلومات المصدر

المستودع
reason-machines/hermes-skills
آخر نشاط في المصدر
١٨ يونيو ٢٠٢٦ في ٠١:٥١
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٥
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
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
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub