Harness — ethenotethan/harness, the opinionated Hermes Agent fork
Portal is the client half of Harness. The gateway is
ethenotethan/harness,
a fork of
NousResearch/hermes-agent
that is rebased onto upstream periodically and documents everything it
changes on a
fork-diff page
its CI refuses to let go stale. The fork is what matters:
stock hermes-agent has no /v1/ws.
Upstream exposes only an OpenAI-compatible HTTP API, so the WebSocket
JSON-RPC endpoint — and with it the wiki, cron-graph, artifact,
learning, file-browser, feed and push-notification RPCs this app is
built on — exists only in Harness. Point Portal at a stock install
and the health probe passes while the socket upgrade fails.
Everything served over that one endpoint: session lifecycle,
prompt.submit, interactive approvals and clarifications,
subagent events, model catalog and switching, session timeline and
usage introspection, and voice.
The gateway advertises its own surface at
/v1/capabilities, so a feature the running gateway
doesn't have stays hidden rather than failing on use — and that
endpoint 404ing is the quickest way to tell you're on stock
upstream. docs/gateway-setup.md
walks through bootstrapping one, including the trap that
hermes update pulls upstream and removes
/v1/ws.
Centaur — a sandboxed harness
Centaur
is a different shape of backend, not a second Hermes: REST for
control, SSE for the stream, no WebSocket. Five endpoints under
/api/session/{thread_key} — create, append the user
turn, execute, interrupt, and an event stream that replays from
?after_event_id=N.
Its wire events are sparse — harness stdout plus execution
lifecycle — so CentaurEventAdapter normalizes them into
the same GatewayEvent enum the gateway emits, and the
chat view model renders a Centaur session unchanged. Because there
is no transcript-fetch endpoint, the persisted SSE cursor is the only
"where was I" marker; it survives launches so a resume doesn't replay
the transcript from zero.
The asymmetry is declared rather than discovered. Centaur runs
non-interactively in a sandbox, so approvals, subagent events,
skills, attachments, model switching, response styles and voice are
all off, and the gateway services — cron, activity inbox, feed,
learning — never apply. It gains what Hermes lacks: workflow
schedules and run history under /api/workflows/*, and
wiki reads over a public REST wiki API instead of
wiki.* RPCs. It also carries a fixed identity, since a
harness is a different agent platform and not a Hermes persona.