一键导入
hermes-leo-interop-sse
Real-time SSE communication between Hermes and Leo/OpenClaw via interop-server.py on port 18900. Includes debug lessons and architecture.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Real-time SSE communication between Hermes and Leo/OpenClaw via interop-server.py on port 18900. Includes debug lessons and architecture.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Diagnose and fix Hermes messaging gateway connectivity issues (Telegram/Discord down, stale locks, PM2 problems)
Backup Hermes agent to GitHub and restore on a new VPS. Covers what to include/exclude, GitHub token requirements, and restore steps. Includes automated scripts.
GitHub auth setup: HTTPS tokens, SSH keys, gh CLI login.
Clone, create, fork, configure, and manage GitHub repositories. Manage remotes, secrets, releases, and workflows. Works with gh CLI or falls back to git + GitHub REST API via curl.
Fetch YouTube video transcripts and transform them into structured content (chapters, summaries, threads, blog posts). Use when the user shares a YouTube URL or video link, asks to summarize a video, requests a transcript, or wants to extract and reformat content from any YouTube video.
Manage Linear issues, projects, and teams via the GraphQL API. Create, update, search, and organize issues. Uses API key auth (no OAuth needed). All operations via curl — no dependencies.
| name | hermes-leo-interop-sse |
| description | Real-time SSE communication between Hermes and Leo/OpenClaw via interop-server.py on port 18900. Includes debug lessons and architecture. |
| category | devops |
hermes-commands/interop-server.py → ThreadedHTTPServer on port 18900
├── POST /broadcast?from=<agent> → deliver to other agent's queue
├── GET /poll?agent=<agent> → read + clear HTTP queue (list)
├── GET /subscribe?agent=<agent> → SSE stream (queue.Queue)
└── GET /status → subscribers + queue sizes
hermes-sse-client.py → SSE client for Hermes (connects as agent=hermes)
openclaw-sse-client → SSE client for Leo (connects as agent=openclaw)
POST /broadcast?from=hermes → deliver to openclaw
POST /broadcast?from=openclaw → deliver to hermes
GET /poll?agent=hermes → read + clear hermes HTTP queue
GET /subscribe?agent=openclaw → SSE stream for Leo
GET /status → JSON with subscribers + queues
Problem: Python's HTTPServer is single-threaded. SSE long-lived connections block ALL other HTTP requests (including health checks).
Fix: Use socketserver.ThreadingMixIn:
from socketserver import ThreadingMixIn
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
daemon_threads = True
allow_reuse_address = True
server = ThreadedHTTPServer(("127.0.0.1", PORT), Handler)
Problem: Every python3 interop-server.py creates a NEW process with FRESH in-memory queues. Old processes stay alive. Broadcast goes to new server, SSE client connects to old server → never meet.
Fix: Always kill ALL existing processes before restart:
pkill -9 -f interop-server.py
sleep 1
ss -tlnp | grep 18900 # verify port is free
python3 interop-server.py
Problem: Two separate queue systems:
queues["openclaw"] — Python list, used by /poll endpointsubscribers["openclaw"] — queue.Queue(), used by SSE streamBroadcast does BOTH:
queues[recipient].append(data) # adds to list
push_to_subscriber(recipient, data) # adds to queue.Queue()
If Leo uses /poll, he consumes from the list. SSE stream keeps blocking on queue.Queue(). If Leo uses SSE only, the list grows but SSE stream works.
Fix: When subscriber reconnects, flush pending messages from list to queue:
q = queue.Queue()
while queues[agent]: # flush pending to new SSE queue
q.put_nowait(queues[agent].pop(0))
subscribers[agent] = q
Problem: Client closes SSE connection while server is writing → BrokenPipeError.
Fix:
try:
self.wfile.write(json.dumps({"delivered": True, ...}).encode())
except BrokenPipeError:
pass
import urllib.request, json, time
SERVER = "http://127.0.0.1:18900"
def main():
req = urllib.request.Request(f"{SERVER}/subscribe?agent=hermes")
with urllib.request.urlopen(req) as r:
for line in r:
line = line.decode().strip()
if line.startswith("data: "):
data = json.loads(line[6:])
# process message
with open("/tmp/hermes-msg-pipe", "w") as f:
f.write(json.dumps(data) + "\n")
while True:
try:
main()
except Exception as e:
time.sleep(5) # auto-reconnect
# Kill all
pkill -9 -f interop-server.py; pkill -9 -f hermes-sse-client.py
# Start server
cd /home/marco/hermes-commands && python3 interop-server.py
# Start Hermes client (background)
python3 hermes-sse-client.py
# Check status
curl http://127.0.0.1:18900/status
{
"agents": {"openclaw": {"online"}, "hermes": {"online"}},
"queues": {"openclaw": 0, "hermes": 0},
"subscribers": {"openclaw": true, "hermes": true}
}
Both true = real-time communication working.
/home/marco/hermes-commands/interop-server.py — server/home/marco/hermes-commands/hermes-sse-client.py — Hermes client