| name | hermesclaw-wechat-multi-agent |
| description | Run Hermes Agent, OpenClaw, and OpenCode simultaneously on a single WeChat account with intelligent message routing |
| triggers | ["set up multiple AI agents on WeChat","run Hermes and OpenClaw on same WeChat account","install HermesClaw for WeChat multi-agent","switch between different AI agents in WeChat","configure dual agent WeChat bot","troubleshoot HermesClaw iLink connection","route messages between Hermes and OpenClaw","add OpenCode to WeChat bot"] |
HermesClaw WeChat Multi-Agent Skill
Skill by ara.so — Hermes Skills collection.
HermesClaw enables running multiple AI agents (Hermes Agent, OpenClaw, OpenCode) on a single WeChat account by acting as a proxy router. It solves the token conflict problem where each gateway tries to exclusively lock the iLink connection, causing 403 errors when running simultaneously.
What HermesClaw Does
HermesClaw is a Python proxy service (~870 lines) that:
- Becomes the sole iLink API poller using a shared WeChat token
- Runs two local proxy servers (ports 19999 for OpenClaw, 19998 for Hermes)
- Bridges OpenCode via its native ACP subprocess protocol
- Routes messages based on commands (
/hermes, /openclaw, /opencode, /both, /three)
- Forwards raw iLink protocol messages (text, voice transcriptions, media CDN URLs)
- Does not process media, decrypt AES, or touch agent memory — each gateway handles its own
Prerequisites
Before installing HermesClaw, you need at least one of these installed:
- OpenClaw with
openclaw-weixin gateway (logged into WeChat)
- Hermes Agent with WeChat gateway configured (
hermes gateway)
- OpenCode CLI (optional, enables
/opencode and /three modes)
Installation
Quick Install (Interactive)
curl -fsSL https://raw.githubusercontent.com/AaronWong1999/hermesclaw/main/install.sh | bash
Non-Interactive Install (CI/CD)
curl -fsSL https://raw.githubusercontent.com/AaronWong1999/hermesclaw/main/install.sh | HERMESCLAW_YES=1 bash
What the Installer Does
- Detects installed gateways (Hermes, OpenClaw)
- Extracts iLink token from gateway account files
- Patches OpenClaw
baseUrl → http://127.0.0.1:19999
- Patches Hermes
WEIXIN_BASE_URL → http://127.0.0.1:19998
- Detects OpenCode CLI at
~/.npm-global/bin/opencode or via command -v opencode
- Installs Python deps:
requests, python-dotenv
- Creates OpenClaw media symlink (handles path mismatch)
- Sets up systemd service
hermesclaw
Manual Installation Steps
If you need to install manually:
cd ~
git clone https://github.com/AaronWong1999/hermesclaw.git
cd hermesclaw
pip3 install requests python-dotenv
cat > .env << 'EOF'
ILINK_TOKEN=your_ilink_token_here
HERMES_PROXY_PORT=19998
OPENCLAW_PROXY_PORT=19999
OPENCODE_CMD=/path/to/opencode
OPENCODE_MODEL=opencode/minimax-m2.5-free
EOF
sudo tee /etc/systemd/system/hermesclaw.service > /dev/null << 'EOF'
[Unit]
Description=HermesClaw WeChat Multi-Agent Router
After=network.target
[Service]
Type=simple
User=$USER
WorkingDirectory=$HOME/hermesclaw
ExecStart=/usr/bin/python3 $HOME/hermesclaw/hermesclaw.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable hermesclaw
sudo systemctl start hermesclaw
Configuration
Environment Variables (.env)
ILINK_TOKEN=your_token_here
HERMES_PROXY_PORT=19998
OPENCLAW_PROXY_PORT=19999
OPENCODE_CMD=/home/user/.npm-global/bin/opencode
OPENCODE_MODEL=opencode/minimax-m2.5-free
LOG_LEVEL=INFO
Gateway Configuration
OpenClaw (~/.openclaw/openclaw-weixin/accounts/*.json):
{
"baseUrl": "http://127.0.0.1:19999",
"token": "your_token"
}
Hermes (~/.hermes/.env):
WEIXIN_BASE_URL=http://127.0.0.1:19998
WEIXIN_TOKEN=your_token
Optional: Fix Hermes Message Splitting
Hermes by default splits long messages by newlines. To send as single messages:
cd ~/hermesclaw
bash fix_hermes_splitting.sh
This patches ~/.hermes/hermesagent/gateways/weixin.py to disable paragraph splitting.
Commands
In-WeChat Commands
Send these in any WeChat conversation with the bot:
/hermes # Route to Hermes Agent only
/openclaw # Route to OpenClaw only
/opencode # Route to OpenCode only (voice coding)
/both # Route to Hermes + OpenClaw (both reply)
/three # Route to all three agents
/whoami # Show current routing mode and status
Default mode is Hermes. In /both or /three modes, replies are prefixed:
[Hermes Agent]
[OpenClaw]
[OpenCode]
Service Management
sudo systemctl status hermesclaw
journalctl -u hermesclaw -f
sudo systemctl restart hermesclaw
sudo systemctl stop hermesclaw
Code Examples
Routing Logic (Python)
class HermesClawRouter:
def __init__(self, token):
self.token = token
self.route_mode = "hermes"
self.hermes_proxy = ProxyServer(19998, token)
self.openclaw_proxy = ProxyServer(19999, token)
self.opencode_bridge = ACPBridge()
def handle_message(self, msg):
text = msg.get("content", "").strip()
if text == "/hermes":
self.route_mode = "hermes"
return self.send_reply(msg, "Switched to Hermes Agent")
elif text == "/openclaw":
self.route_mode = "openclaw"
return self.send_reply(msg, "Switched to OpenClaw")
elif text == "/opencode":
self.route_mode = "opencode"
return self.send_reply(msg, "Switched to OpenCode")
elif text == "/both":
self.route_mode =
.send_reply(msg, )
text == :
.route_mode =
.send_reply(msg, )
.route_mode == :
.hermes_proxy.queue_message(msg)
.route_mode == :
.openclaw_proxy.queue_message(msg)
.route_mode == :
.opencode_bridge.send_message(msg)
.route_mode == :
.hermes_proxy.queue_message(msg)
.openclaw_proxy.queue_message(msg)
.route_mode == :
.hermes_proxy.queue_message(msg)
.openclaw_proxy.queue_message(msg)
.opencode_bridge.send_message(msg)
Proxy Server Implementation
class ProxyServer:
def __init__(self, port, token):
self.port = port
self.token = token
self.message_queue = queue.Queue()
def run(self):
app = Flask(__name__)
@app.route("/v1/weixinbot/getupdate", methods=["POST"])
def get_update():
try:
msg = self.message_queue.get(timeout=25)
return jsonify(msg)
except queue.Empty:
return jsonify({"type": "heartbeat"})
@app.route("/v1/weixinbot/sendmessage", methods=["POST"])
def send_message():
data = request.json
response = requests.post(
"https://ilinkai.weixin.qq.com/v1/weixinbot/sendmessage",
json=data,
headers={"Authorization": f"Bearer {self.token}"}
)
return response.json()
app.run(host="127.0.0.1", port=self.port)
OpenCode ACP Bridge
class ACPBridge:
def __init__(self, cmd, model):
self.cmd = cmd
self.model = model
self.process = None
def start(self):
self.process = subprocess.Popen(
[self.cmd, "acp", "--model", self.model],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1
)
def send_message(self, msg):
acp_msg = {
"type": "user_message",
"content": msg.get("content", ""),
"context": {
"from": msg.get("from_wxid"),
"chat_id": msg.get("room_wxid", msg.get("from_wxid"))
}
}
self.process.stdin.write(json.dumps(acp_msg) + "\n")
self.process.stdin.flush()
def read_response(self):
while True:
line = self.process.stdout.readline()
line:
response = json.loads(line)
response.get() == :
response.get()
Common Patterns
Pattern 1: Voice to OpenCode
OpenCode excels at voice-based coding. Route voice messages:
User: /opencode
User: [voice message: "Create a Python script that reads CSV and generates a bar chart"]
OpenCode: [creates chart.py with pandas and matplotlib]
Pattern 2: Dual-Agent Comparison
Get different perspectives on the same question:
User: /both
User: What's the best way to handle rate limiting in a REST API?
[Hermes Agent]: Use exponential backoff with jitter...
[OpenClaw]: Implement a token bucket algorithm...
Pattern 3: Seamless Switching
Switch contexts without losing conversation history:
User: /hermes
User: Explain async/await in Python
[Hermes responds]
User: /openclaw
User: Now write an example with aiohttp
[OpenClaw responds with code]
Pattern 4: Media Forwarding
HermesClaw forwards raw iLink messages, so each gateway handles media natively:
Troubleshooting
Problem: 403 Token Conflict
Symptom: One gateway works, the other gets 403 errors or no messages.
Solution:
sudo systemctl status hermesclaw
grep baseUrl ~/.openclaw/openclaw-weixin/accounts/*.json
grep WEIXIN_BASE_URL ~/.hermes/.env
sudo systemctl restart hermesclaw
Problem: Messages Not Routed
Symptom: /hermes or /openclaw commands don't switch mode.
Solution:
journalctl -u hermesclaw -n 100
curl -X POST http://127.0.0.1:19998/v1/weixinbot/getupdate \
-H "Content-Type: application/json" \
-d '{}'
Problem: OpenCode Not Found
Symptom: /opencode or /three commands don't work.
Solution:
npm install -g opencode-ai
command -v opencode
cd ~/hermesclaw
echo "OPENCODE_CMD=$(command -v opencode)" >> .env
sudo systemctl restart hermesclaw
Problem: Media Path Errors
Symptom: OpenClaw can't find media files.
Solution:
ln -sf ~/.openclaw/openclaw-weixin/files ~/hermesclaw/openclaw-weixin-files
sudo systemctl restart hermesclaw
Problem: Long Messages Split
Symptom: Hermes sends replies as multiple short messages.
Solution:
cd ~/hermesclaw
bash fix_hermes_splitting.sh
Problem: Token Extraction Failed
Symptom: Installer can't find iLink token.
Manual extraction:
grep -r "token" ~/.openclaw/openclaw-weixin/accounts/*.json
grep WEIXIN_TOKEN ~/.hermes/.env
echo "ILINK_TOKEN=your_extracted_token" >> ~/hermesclaw/.env
Architecture Overview
┌─────────────────────────────────────┐
│ iLink API (WeChat) │
│ ilinkai.weixin.qq.com │
└──────────────┬──────────────────────┘
│
(sole poller)
│
┌──────────────▼──────────────────────┐
│ HermesClaw Router │
│ - Routes by /hermes /openclaw │
│ - Queues raw iLink messages │
│ - Prefix replies in multi-mode │
├─────────┬─────────┬─────────────────┤
│ Proxy A │ Proxy B │ ACP Bridge │
│ :19999 │ :19998 │ (subprocess) │
└────┬────┴────┬────┴────┬────────────┘
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│OpenClaw │ │ Hermes │ │OpenCode │
│ gateway │ │ gateway │ │ CLI │
└─────────┘ └─────────┘ └─────────┘
Uninstallation
Quick Uninstall
sudo systemctl stop hermesclaw
sudo systemctl disable hermesclaw
sudo rm -f /etc/systemd/system/hermesclaw.service
sudo systemctl daemon-reload
find "$HOME" -maxdepth 5 -name "*.json.bak" -path "*/openclaw-weixin/accounts/*" \
-exec sh -c 'for f; do cp "$f" "${f%.bak}"; done' sh {} +
[ -f "$HOME/.hermes/.env.bak" ] && cp "$HOME/.hermes/.env.bak" "$HOME/.hermes/.env"
rm -rf "$HOME/hermesclaw"
Testing
HermesClaw includes 82 pytest tests covering core routing, proxy servers, ACP bridge, and recovery scenarios:
cd ~/hermesclaw
pip3 install pytest pytest-mock
python3 -m pytest tests/ -v
Key test files:
tests/test_core.py — Routing logic, mode switching
tests/test_proxy.py — Proxy server message queuing
tests/test_acp.py — OpenCode bridge protocol
tests/test_recovery.py — Connection failures, retries
Advanced Usage
Custom OpenCode Models
Edit .env to use different free models:
OPENCODE_MODEL=opencode/minimax-m2.5-free
OPENCODE_MODEL=opencode/deepseek-free
OPENCODE_MODEL=opencode/qwen-free
OPENCODE_MODEL=opencode/glm-free
All models are free and require no API keys.
Programmatic Control
Control HermesClaw from other scripts:
import requests
requests.post("http://127.0.0.1:19998/control", json={
"action": "set_mode",
"mode": "both"
})
status = requests.get("http://127.0.0.1:19998/status").json()
print(f"Current mode: {status['mode']}")
print(f"Queued messages: {status['queue_size']}")
Debug Logging
Enable verbose logging:
echo "LOG_LEVEL=DEBUG" >> ~/hermesclaw/.env
sudo systemctl restart hermesclaw
journalctl -u hermesclaw -f
References