IOWAP Hermes Integration
IOWAP (Infrastructure · Offloading · Workload Assignment
Platform) is a distributed capability
framework: nodes claim what they can do, the relay connects them, and
workloads get routed to whichever node actually has the capability.
A Hermes desktop plugin that puts
IOWAP fleet data into the desktop app:
- Statusbar chip — live dot +
N/Mnodes online, click opens the fleet page - Fleet pane (right zone, draggable) — compact node list
- Fleet page (
/iowap-fleet, sidebar nav + ⌘K) — full overview: status,
load, queue depth, capabilities per node, plus an Activity section
(daemon self-sight, tracked tasks with per-stage status dots,
task-capability provider health) - Tasks page (
/iowap-tasks, sidebar nav + ⌘K) — submit a task to any
task-type capability (capability picker, JSON payload, optional name),
track an existing task by its relay id, and watch tracked tasks live
(per-stage status dots, result previews, artifacts). Tasks submitted from
agent sessions viaiowap-task submit(repotools/iowap-task, installed
at~/.local/bin/iowap-task) land in the same track store — the bridge
wrapsnode-cli task submitand merges into
~/.hermes/plugin-data/iowap/task-track-iowap.json. Owner-directed tasks
(--owner <node_id>) show asdelegatedrows (result unreadable from
this node — server-side T-005g scoping) instead of fetch errors. - Notifications page (
/iowap-notifications, sidebar nav + ⌘K) —
switches for chat posts, pane tiles and chip flash (tasks / fleet
areas), chat target (origin or manual session id), draft | direct mode
and a bounded event log (100 entries, clearable). Everything defaults
OFF. - ⌘K commands — refresh fleet data, notify fleet status, open the pages
Task watcher & fleet watch
- Task watcher — new-task acknowledgement, stage results and final
states are posted automatically into the active chat (host.composer
with user-typed authority, fail-closed, never a broadcast: without a
mounted composer the update surfaces as a toast; a failed direct submit
fails honestly instead of silently degrading into a draft). Posted lines
carry the task id. Toggle: the switch on the Tasks page or ⌘K "IOWAP:
toggle task watch posts" (persisted; the sweep registry is persisted
too, so reloads and redeploys never double-post). Tasks non-terminal
for more than 5 minutes get a one-time long-run hint. Chat lines
follow the app locale (en/de/es/fr shipped). - Fleet watch — node status transitions warn in chat: a node going
offline posts a one-time ⚠️ warning, coming back posts a ✅ recovery
line; relay reachability is watched the same way. Runs on the fleet
data the chip/pane/page already poll — no extra polling.
Architecture
desktop renderer (plugin.js) gateway process (plugin_api.py) relay
┌─────────────────────┐ ctx.rest ┌──────────────────────────┐ node-cli ┌───────┐
│ chip / pane / page │ ──────────► │ /api/plugins/iowap/fleet │ ─────────► │ :8788 │
└─────────────────────┘ └──────────────────────────┘ └───────┘
The desktop frontend never touches relay HTTP or tokens. The backend
(/api/plugins/iowap/*) shells out to node-cli --json, which owns all relay
auth and token handling (~/.relay/*). Relay tokens never enter the renderer.
Install
Install straight from the plugin catalog:
hermes plugins install iowap
Updates land through the same channel — the catalog keeps a pinned
version and hermes plugins update iowap pulls it:
hermes plugins update iowap
Requires the node-cli from the
iowap-node framework on the
desktop host (it is not a PyPI package — install with
git clone https://github.com/iowap-org/iowap-node && pip install -e .)
and a logged-in node state (~/.relay/iowap-agent.*). Then restart the
Hermes desktop app (the backend imports live in the gateway process — a
plugin reload is not enough the first time) and run Reload desktop
plugins (⌘K) afterwards for frontend edits. Without the backend the UI
degrades gracefully to an onboarding hint.
How the backend finds node-cli (the desktop-spawned gateway does not
inherit the login-shell PATH — resolution must never depend on it):
~/.relay/node.yaml top-level node_cli_path pin → PATH → a short
list of known venv locations. The pin is written by node-cli itself
(every invocation re-stamps its own absolute path, drift-guarded and
self-healing through capabilities publish; requires iowap-node
≥ 2.3.20 — with an older wheel, run any node-cli command once or set
the key by hand). This backend reads the key strictly read-only; a stale
pin falls through to the next link instead of blocking.
Install from source (dev)
For repo checkouts and development — catalog users don't need this
section.
Desktop half (chip, pane, page, commands):
mkdir -p ~/.hermes/desktop-plugins/iowap
curl -o ~/.hermes/desktop-plugins/iowap/plugin.js \
https://raw.githubusercontent.com/iowap-org/iowap-hermes-integration/main/desktop/plugin.js
curl -o ~/.hermes/desktop-plugins/iowap/plugin.yaml \
https://raw.githubusercontent.com/iowap-org/iowap-hermes-integration/main/plugin.yaml
Backend half (fleet data through node-cli):
mkdir -p ~/.hermes/plugins/iowap/dashboard
curl -o ~/.hermes/plugins/iowap/dashboard/manifest.json \
https://raw.githubusercontent.com/iowap-org/iowap-hermes-integration/main/dashboard/manifest.json
curl -o ~/.hermes/plugins/iowap/dashboard/plugin_api.py \
https://raw.githubusercontent.com/iowap-org/iowap-hermes-integration/main/dashboard/plugin_api.py
hermes config set plugins.enabled '["iowap"]'
Update an installed plugin (from a repo checkout):
tools/deploy.sh # installs both halves + plugin.yaml, creates the parent
# dirs, verifies md5; frontend hot-reloads,
# backend edits need one app restart
The plugin id is iowap — the desktop folder name must match it (SDK
requirement). Enable the desktop half in Capabilities → Plugins if it
stays off.
Status
v0.4.0 — chip + pane + fleet page + palette commands + tasks page
(submit, track, delegated rows), live data via node-cli; the task
watcher posts submit/progress/final updates and fleet warnings (node
down/back, relay reachability) into the chat, switchable from ⌘K or the
Tasks page; UI in en/de/es/fr. Release notes:
CHANGELOG.md. Agent sessions
join through the iowap-task bridge (repo tools/, installed at
~/.local/bin/iowap-task) into a shared flock-protected track store. The
relay health probe runs through node-cli itself (node-cli server health)
— no raw HTTP and no hand-parsed relay URL on the backend side; the target
pin (relay_config.json, mDNS fallback) stays node-cli's business. Per-node
detail
(load_source) distinguishes host-load (loadavg) from agent-scoped cgroup
values — do not compare load numbers across nodes.
Layout of this repo
desktop/plugin.js ← desktop half (→ ~/.hermes/desktop-plugins/iowap/)
dashboard/manifest.json ← backend manifest (→ ~/.hermes/plugins/iowap/dashboard/)
dashboard/plugin_api.py ← backend routes (→ ~/.hermes/plugins/iowap/dashboard/)
tests/ ← pytest suite (track store, delegated rows, cache eviction)
tools/iowap-task ← session bridge (→ ~/.local/bin/iowap-task)
tools/deploy.sh ← install both halves + md5 verify
README.md
License
MIT — see LICENSE.
README from the reviewed commit 541b42e; it updates when the author re-pins.

Kesuek