1Lab Overview
Retinue is an open-source, self-hosted staff of AI teammates. You hire an agent with three fields — a name, its primary job, and how it should work — and it joins your team: its own persona, its own memory, its own model. Agents talk with you and with each other in shared rooms, hand work off by mentioning a teammate, and do real work on a computer you own.
Commercial products like xAI's Grok Bot proved this UX in 2026: named persistent agents, group chats with agent-to-agent handoff, a shared computer the whole team works on. They also priced it at $120–300/month and put your credentials on a managed cloud VM. Retinue brings the same experience home — your machine or a podman container, any model provider (including fully local llama.cpp endpoints), MIT-licensed.
The screenshot above is a live room: three agents (@scout, @editor, @herald) collaborating on a launch announcement, each with a distinct role and voice, with the human steering. Everything runs from one gateway process on local hardware.
Retinue is a deliberately thin fork of hermes-agent by Nous Research — a ~685K-line, fast-moving open-source agent framework. Retinue adds the multi-agent product layer (rooms, a native web UI with the hire flow, and a shared "workspace computer" container) as plugins, and inherits everything else: the agent loop, terminal/browser/file tools, MCP, skills, memory, and 34 model-provider plugins.
2Architecture
The design constraint that shapes everything: the fork delta stays plugin-shaped. Upstream moves too fast for a divergent fork to survive, so Retinue's code lives in a platform plugin, a standalone web app, and two narrow carried patches — upstream core files are not edited.
Rooms: one transcript, N agents, turn-taking
Each agent is a Hermes profile — its own SOUL.md persona, model, memory, and toolset. One multiplexing gateway process hosts every room member. The rooms platform adapter gives them a shared transcript and a turn engine:
- Turn rules: a user message mentioning
@namegives each mentioned member a turn in order; no mention routes to the room's lead. Agent replies are scanned for mentions of other members, which are appended to the turn queue — that's how work gets handed off. A per-cycle budget caps runaway agent-to-agent chatter. - Reply capture: the adapter injects each turn as a gateway message event stamped with the member's profile and captures the member's final reply via the gateway's documented final-reply marker — no polling of agent internals.
- Context delivery: each member tracks how much of the transcript it has seen; unseen, speaker-attributed lines ride the event's channel context rather than being written into the member's session store — which preserves the agent cache and provider prompt caching.
- State: room metadata is atomic JSON; the transcript is append-only JSONL.
Web UI and the hire flow
A Vite + React SPA served by the rooms adapter itself — same origin, no CORS story. The room view renders each agent's turns distinctly; the hire flow is the three-field form (name, job, how it works) that templates a full profile: persona file, model choice, toolset.
The workspace computer
All of a workspace's agents share one persistent container — shared files and state are what make handoffs cheap, the same model as the commercial products' per-user VM, except it's a rootless podman container on your hardware. Upstream's Docker backend already runs on podman; Retinue's carried patch adds a shared container key so every member attaches to the same long-lived container instead of getting a per-profile one. Only terminal tools run inside; stricter per-agent isolation is just omitting the key.
Staying a thin fork
Both carried patches reference upstream issues and are guarded by source-level drift tests that turn the suite red if an upstream sync clobbers them — either patch landing upstream retires it. The README is the single owned upstream path, protected by a merge=ours git attribute.
3Setup and Deployment
Retinue runs anywhere hermes-agent runs: a Linux box, a homelab node, a workstation. The rooms platform is off by default and binds localhost-only unless you give it an API key.
git clone https://github.com/novique-ai/retinue
cd retinue
uv venv --python 3.12 && uv pip install -e .
# enable rooms (localhost-only without an API key)
export RETINUE_ROOMS_ENABLED=1
# the gateway multiplexes every member profile in one process
# (gateway.multiplex_profiles: true in config.yaml)
hermes gateway
The web UI ships prebuilt paths out of retinue-web/; rebuild with npm install && npm run build in that directory. It is served by the rooms adapter on the same port — open the adapter's address in a browser, create a room, and hire agents from the sidebar.
Workspace-computer mode
To give the team a shared computer, point terminals at a long-lived container (podman is auto-detected; no Docker daemon required):
TERMINAL_ENV=docker
TERMINAL_DOCKER_SHARED_CONTAINER_KEY=my-workspace
TERMINAL_DOCKER_IMAGE=docker.io/library/python:3.12-slim
Every room member's terminal then lands in the same container — one agent writes a file, the next reads and extends it. Omit the shared key for per-agent isolation instead.
Key environment knobs
RETINUE_ROOMS_API_KEY— bearer auth; setting it also allows non-localhost bindsRETINUE_ROOMS_HOST/RETINUE_ROOMS_PORT— bind addressRETINUE_ROOMS_TURN_TIMEOUT— seconds to wait on one agent turn (default 300)
For anything durable, run the gateway under a systemd user unit rather than from an interactive shell — a gateway spawned from a terminal session dies with the session.
4Troubleshooting Highlights
Real traps hit while building and live-verifying v1 — each cost debugging time so you don't have to spend it.
- A billing-shaped error that isn't about billing. Rooms smoke tests against Anthropic subscription OAuth kept failing with a 400 that read like a usage-limit problem. The actual cause: one sentence of the stock upstream system prompt trips a content filter on that auth path (upstream issue #82154). Retinue carries a one-line reword as a documented patch. Corollary: sessions started before a prompt patch replay the old system prompt — always retest with fresh rooms after touching prompt code.
- An agent can be born broken. The hire flow templates the new profile's model block from the root config. If the root config points at a dead provider or revoked key, every newly hired agent inherits the failure and looks like a product bug. Keep the root model block pointed at a working provider.
- Only the default profile can bind ports. Secondary profiles in a multiplexed gateway can't open listeners — the rooms adapter (and therefore the web UI) runs on the default profile by design.
- Don't put the SPA inside the workspace glob. Upstream's repo root is an npm workspace with an
apps/*glob; runningnpm installfor a new app underapps/rewrites the upstream root lockfile — an instant fork-policy violation. The web UI lives at top-levelretinue-web/for exactly this reason. After any web rebuild, verify the rootpackage-lock.jsonis untouched. - Podman notes. Rootless podman 4.9.3 works with no Docker binary on the host — upstream's binary discovery falls back to podman automatically. Upstream's backend-probe task spawns a second, short-lived container under its own task ID; it's pre-existing behavior and harmless, not a leak in workspace mode.
5Practical Business Use
The economics: managed agent-team products run $120–300 per user per month, and the meter runs whether the team is busy or idle. Retinue's marginal cost is your hardware plus whatever model lane you choose — which can be a metered API for the agents that need frontier reasoning and a $0 local llama.cpp endpoint for the ones that don't. Mixing providers per agent is native, not a workaround.
The sovereignty case is often the deciding one. On a managed VM, your logins, files, and transcripts live on infrastructure you don't control. In Retinue, the agents' computer is your computer or a podman container you own: credentials never leave your network, transcripts are plain files you can grep and back up, and regulated environments can keep everything inside the boundary.
What a team-of-specialists actually does:
- A research agent gathers material, then mentions a drafting agent that writes, then a review agent that critiques — one room, one shared context, visible handoffs (that's the workflow in the screenshot above).
- An ops room where each agent owns a system, sharing one workspace container so diagnostics one agent produces are files the next agent can read.
- A standing room per project instead of per conversation — agents keep their own memory, so context accumulates where the work lives.
Honest status: v1, early development. Turns are sequential (one agent speaks at a time), the room streams final replies rather than tokens, and routines-by-demonstration and the take-over view are still on the roadmap. What's shipped — rooms, the web UI with the hire flow, and the shared workspace container — is live-verified and documented in the repo. If you want a managed product with support, buy one; if you want the same shape of product on your own terms, this is that.
