- gpu-fleet: Corrected architecture (direct GPU, no router in path). Updated context values (RTX 3090=256K, not 128K). Added api-key standardization requirement. - gpu-self-heal: Added Lessons Learned section with 5 critical findings: L1: API key standardization (RTX 5070 sk-loc...5678 vs not-needed) L2: Fallback chain cascading failure loop detection L3: Verify running state, not documentation L4: Infisical fallback requirement (.env must have uncommented key) L5: Zulip event queue can silently die after ~40 reconnects - litellm-self-heal: Updated status manual-only→deployed, cron schedule - litellm-api-keys: Added Infisical token expiry warning + .env fallback - hermes-config-template: Rule 3 updated with .env fallback requirement
8.2 KiB
kind, name, description, agent, version, status, runtime_contract
| kind | name | description | agent | version | status | runtime_contract |
|---|---|---|---|---|---|---|
| function | hermes-zulip-plugin | Installs or updates the Zulip platform plugin for any Hermes agent from the canonical zulip-platform-plugins repo (master branch). Ensures the agent runs the latest adapter with all Zulip chat fixes (_strip_html, streaming, event recovery). Verifies the installation, restarts the gateway, and sends a relay success signal. | abiba | 1.0.0 | active | 2 |
Hermes Zulip Plugin — Install & Repair
Single-shot function that pulls the latest zulip-platform plugin from the canonical git repo, installs it to the correct Hermes bundled plugin path, verifies the installation, and signals completion.
Distinct from hermes-zulip-restore: this contract is focused on the plugin
layer and a targeted gateway restart. It does NOT verify env credentials or
run a live Zulip connection test. Use hermes-zulip-restore for full
connectivity recovery including end-to-end DM validation.
Parameters
| Param | Type | Required | Default | Description |
|---|---|---|---|---|
target |
string | yes | — | Agent name: mumuni, tanko, koby, or shumba |
branch |
string | no | master |
Git branch to pull (overridable for pinning) |
Maintains
- plugin_installed: bool — Whether all three adapter files exist at the bundled path
- plugin_version: string — Git commit SHA of the installed version
- strip_html_present: bool — Whether
_strip_htmlfix is in the installed adapter - signal_sent: bool — Whether relay success message was dispatched
Postconditions
- All three adapter files (
__init__.py,adapter.py,plugin.yaml) present in<HERMES_HOME>/hermes-agent/plugins/platforms/zulip/ _strip_htmlfunction exists inadapter.py(slash-command fix, commit55ca15d+)- Installed version matches HEAD of the requested branch
- Relay success signal sent to Hermes agent's inbox
Requires
- SSH access to target host (direct or via amdpve for CTs)
- Git repo at
https://git.sysloggh.net/SyslogSolution/zulip-platform-plugins.git - Python 3 with
httpxinstalled on target
Live-State Fields
| Host | CT | Proxmox | IP (direct) | Hermes Home | User |
|---|---|---|---|---|---|
| Mumuni | CT114 | — | 192.168.68.123 | /root/.hermes | root |
| Tanko | CT112 | amdpve | 192.168.68.122 | /home/jerome/.hermes | jerome |
| Koby | CT111 | amdpve | 192.168.68.129 | /root/.hermes | root |
| Shumba | — | — | 192.168.68.119 | /home/lucky/.hermes | lucky |
| Field | Value | Trust |
|---|---|---|
| Git repo | https://git.sysloggh.net/SyslogSolution/zulip-platform-plugins.git |
✅ Verified |
| Default branch | master (contains all merged fixes including feat/zulip-streaming) |
✅ Verified |
| Bundled adapter path | <HERMES_HOME>/hermes-agent/plugins/platforms/zulip/ |
✅ Verified |
| Adapter files | __init__.py, adapter.py, plugin.yaml |
✅ Verified |
| Strip-html commit | 55ca15d (minimum) |
✅ Verified |
Execution
Step 1: Resolve Target
Map target to host, CT ID, hermes_home, and user from the live-state table.
For CT112 and CT111, route through ssh root@amdpve then pct exec <id>.
Step 2: Pull Latest Plugin Source
On the target host:
# Ensure deploy scratch space
mkdir -p /tmp/zulip-deploy
cd /tmp/zulip-deploy
# Clone or pull
if [ -d zulip-platform-plugins ]; then
cd zulip-platform-plugins
git fetch origin
git checkout {{branch}}
git pull origin {{branch}}
else
git clone --branch {{branch}} \
https://git.sysloggh.net/SyslogSolution/zulip-platform-plugins.git
cd zulip-platform-plugins
fi
# Capture installed version
INSTALLED_SHA=$(git rev-parse HEAD)
echo "Installed SHA: $INSTALLED_SHA"
# Verify we're at HEAD
HEAD_SHA=$(git rev-parse origin/{{branch}})
if [ "$INSTALLED_SHA" = "$HEAD_SHA" ]; then
echo "At latest commit on {{branch}}"
else
echo "WARNING: not at HEAD — $INSTALLED_SHA vs $HEAD_SHA"
fi
Step 3: Install Plugin Files
# Ensure target directory exists
mkdir -p {{hermes_home}}/hermes-agent/plugins/platforms/zulip
# Copy adapter files
cp plugins/platforms/zulip/adapter.py \
plugins/platforms/zulip/__init__.py \
plugins/platforms/zulip/plugin.yaml \
{{hermes_home}}/hermes-agent/plugins/platforms/zulip/
# Fix ownership (Tanko only — runs as jerome user)
[ "{{target}}" = "tanko" ] && chown -R jerome:jerome \
{{hermes_home}}/hermes-agent/plugins/platforms/zulip/
echo "Plugin files installed"
Step 4: Verify Installation
# Check all three files exist
for f in __init__.py adapter.py plugin.yaml; do
if [ -f "{{hermes_home}}/hermes-agent/plugins/platforms/zulip/$f" ]; then
echo "✅ $f present"
else
echo "❌ $f MISSING"
exit 1
fi
done
# Verify _strip_html fix
grep -q "_strip_html" {{hermes_home}}/hermes-agent/plugins/platforms/zulip/adapter.py \
&& echo "✅ _strip_html fix present" \
|| echo "❌ _strip_html MISSING — plugin may be stale"
# Show installed plugin.yaml version
grep "^version:" {{hermes_home}}/hermes-agent/plugins/platforms/zulip/plugin.yaml || true
Step 5: Restart Gateway
Plugin changes require a gateway restart to take effect:
cd {{hermes_home}}/hermes-agent
# Use venv if available
python3 -m hermes_cli.main gateway restart 2>&1 || \
venv/bin/python -m hermes_cli.main gateway restart 2>&1
Wait for restart to complete (up to 45s), then confirm:
grep "Gateway running" {{hermes_home}}/logs/gateway.log | tail -1
Expected: Gateway running with N platform(s) where N > 1 (includes zulip).
Quick smoke check — confirm zulip platform loaded:
grep -E "zulip.*loaded|zulip.*registered" {{hermes_home}}/logs/gateway.log | tail -3
If gateway fails to restart, check logs for the crash cause before proceeding.
Step 6: Send Relay Success Signal
On the Abiba host (local), dispatch a relay message to the target agent:
ra-h-os-createRelayNode:
title: "Zulip plugin updated — {{target}}"
source: |
Plugin installed from {{branch}} @ {{INSTALLED_SHA}}
All 3 adapter files verified at {{hermes_home}}/hermes-agent/plugins/platforms/zulip/
_strip_html fix: PRESENT
Timestamp: {{timestamp}}
description: "hermes-zulip-plugin completed for {{target}} — plugin layer healthy"
Step 7: Report
Compile results into a single status block:
| Field | Value |
|---|---|
| Target | {{target}} |
| Branch | {{branch}} |
| Commit SHA | {{INSTALLED_SHA}} |
| Files installed | __init__.py, adapter.py, plugin.yaml |
_strip_html |
`{{present |
| Gateway restarted | `{{yes |
| Signal sent | `{{yes |
Known Failure Modes
| Symptom | Root Cause | Recovery |
|---|---|---|
| Git clone fails | No network or repo unreachable | Check VPN/network, verify repo URL |
| Permission denied on copy | Wrong user for target | Use correct user (jerome for Tanko, root for others) |
_strip_html missing after install |
Branch doesn't include commit 55ca15d |
Switch to feat/zulip-streaming branch |
| Plugin files missing after copy | Target directory doesn't exist | Ensure mkdir -p ran successfully |
| Relay signal fails | MCP bridge unreachable | Signal manually via ra-h-os-createRelayNode |
Edge Differences from hermes-zulip-restore
| Concern | hermes-zulip-restore | hermes-zulip-plugin |
|---|---|---|
| Env credential check | ✅ Full ZULIP_* verification | ❌ Out of scope |
| Gateway restart | ✅ Full restart + state validation | ✅ Targeted restart + smoke check |
| Live connection test | ✅ Validates zulip.state = connected |
❌ Out of scope |
| Plugin deploy | ✅ Includes deploy as one step | ✅ Primary purpose |
| Version tracking | ❌ Implicit | ✅ Explicit SHA capture |
| Signal dispatch | ❌ None | ✅ Relay message to target |
For full connectivity recovery after a plugin install, chain this contract
with hermes-zulip-restore (skip its Step 2 to avoid redundant deploy).
Last updated: 2026-07-08 — Switched default branch to master; added
gateway restart step. If outstanding unmerged feature branches exist, address
them in a follow-up merge after this contract completes.