v0.5.9 UX release: this package includes the interactive v0.1-style install/management flow while keeping the v0.5.9 Smart Router and 9router architecture. Run
./install.sh, use./install.sh --dry-runto preview,./install.sh --no-startto configure without starting containers, and./manage.sh menufor interactive management. n8n MCP provisioning/verification and token-management commands are available through./manage.sh help.
A self-hosted Linux stack for running Hermes Agent, its Telegram bot/agent, Open WebUI, optional n8n, and secure execution tooling behind Hermes Smart Router v0.5.9 and a selectable router backend (9router or OmniRoute).
Router backend:
./install.shinstalls either the9routeror theomniroutebackend profile onmain; the legacyhermes-omniroute-linux-stackbranch is obsolete.
- Canonical changelog
- Operations Center user guide
- Multi-agent orchestration - plan, approve/reject, review
- Release process
- Smart Router complete user guide - every Operations Center page, client API, recipes, configuration, and troubleshooting
- Smart Router client API
- Smart Router Docker Hub notes
- Execution Broker Docker Hub notes
Telegram API
↑
│ outbound polling
│
Hermes Telegram Agent
│
▼
Hermes Agent ───────────────┐
│
Open WebUI ─────────────────┼──► Hermes Smart Router v0.6.1
│ │
n8n / other clients ────────┘ │
├─ fast → backend tier default
├─ standard → backend tier default
└─ strong → backend tier default
│
▼
9router / OmniRoute
│
▼
Providers / Models
Telegram is handled by the Hermes gateway. It is not a separate Docker service: Hermes polls the Telegram Bot API and serves allowed Telegram users through the same agent/runtime used by the rest of the stack.
main supports both router backends behind Compose profiles. Install chooses
one backend, and the selected profile drives the Smart Router upstream, the
route-profile aliases, and the Hermes/Open WebUI/n8n client connections.
Hermes / Telegram / Open WebUI / n8n
│
▼
Smart Router v0.6.1
│
▼
9router / OmniRoute
│
▼
Providers
9router(profile9router) is the single-port OpenAI-compatible gateway on 20128 with automatic key provisioning.omniroute(profileomniroute) exposes the dashboard on 20128 and its OpenAI-compatible API on 20129../install.shchooses one backend on fresh installs and can switch an existing install between them without losing data;COMPOSE_PROFILESrecords the selection. Hermes, Open WebUI, n8n, and the Smart Router behave identically for both backends.- The legacy
hermes-omniroute-linux-stackbranch is obsolete; its OmniRoute configuration now lives inmainbehind theomnirouteprofile.
-
Visual Workflow Studio, Agent Studio, Router Pipeline Studio, and Knowledge Pipeline Studio.
-
New persistent Knowledge Pipeline registry/API.
-
Reworked Operations Center navigation around Observe / Build / Tools / Routing / Access / System.
-
Redesigned semantic light theme for Operations Center and improved Flight Deck light mode.
-
Execution & Approvals now distinguishes browser network/CORS/bind failures from invalid-key failures.
-
./manage.sh configure-execution-admin-browser ORIGIN [PRIVATE_IPV4]configures exact private browser access without printing the key. -
Companion Hermes Execution Broker target:
0.1.3. -
Light/dark Operations Center and Flight Deck themes.
-
Consistent reversible Enable/Disable vs permanent Delete/Uninstall lifecycle controls for Agents, Teams, Groups, Plugins, Skills, and Routes.
-
Hybrid lexical/vector RAG with reranking, OpenAI-compatible embeddings, and PostgreSQL/pgvector acceleration.
-
Request traces, guardrails, advanced router pipelines, model catalog, workflow graphs, prompt versions, datasets/evaluations, marketplace, and onboarding surfaces.
-
PostgreSQL + pgvector + Redis + two-router HA example, HA smoke tests, and load-test tooling.
-
OIDC remains the completed interactive enterprise login path; LDAP/SAML/SCIM are connector foundations requiring deployment-specific integration testing.
-
Hermes Agent running in Docker
-
Telegram bot/agent integration through Hermes
-
Numeric Telegram user allowlist
-
Optional Telegram home chat for cron results and notifications
-
Hermes Smart Router v0.5.9
-
OpenAI-compatible
autorouting aliases -
9router provider/model gateway
-
Open WebUI integration
-
Optional n8n integration
-
Optional Caddy reverse proxy
-
Optional Hermes dashboard and OpenAI-compatible API
-
Persistent state under
data/ -
Non-root and read-only Smart Router runtime
-
Optional approval-gated Docker, SSH, and sandbox execution
-
Dedicated Telegram approval bot support for privileged execution workflows
-
Local-only service bindings by default where appropriate
- Linux
- Bash
- Docker Engine
- Docker Compose plugin
- Git
- A Telegram BotFather token if Telegram is enabled
- At least one AI provider configured through 9router
Check Docker:
docker version
docker compose versionClone the repository:
git clone https://github.com/Afsharidevops/hermes-linux-stack.git
cd hermes-linux-stack
git switch mainMake the scripts executable:
chmod +x install.sh manage.shRun the installer:
./install.shThe installer guides you through the selected services and configuration.
Depending on your choices it can configure:
- 9router
- Hermes Agent
- Telegram
- Smart Router
- Open WebUI
- n8n
- Hermes dashboard/API
- optional execution capabilities
- optional Caddy/public access
Telegram is a first-class Hermes interface in this stack.
The runtime path is:
Telegram user
│
▼
Telegram Bot API
│
▼
Hermes gateway
│
▼
Smart Router
│
▼
9router
│
▼
Provider / Model
During installation, enable Telegram when prompted.
You will be asked for:
- your Telegram BotFather token
- one or more allowed numeric Telegram user IDs
- an optional Telegram home chat ID
The bot token and Telegram configuration are stored under the Hermes runtime data rather than committed to Git.
Do not use Telegram usernames as authorization values.
Use numeric Telegram IDs.
A common way to discover your numeric ID is through a Telegram user-ID bot such as @userinfobot.
After startup, open the bot and send:
/start
If a home chat has not been configured, you can set one from the intended chat with:
/sethome
The home chat can receive cron output and cross-platform notifications.
./manage.sh show-telegram-users./manage.sh add-telegram-user 123456789./manage.sh set-telegram-users 123456789,987654321The Hermes service is recreated automatically when the managed Telegram allowlist changes.
Check Hermes logs:
./manage.sh logs hermesVerify:
- the BotFather token is valid
- allowed users are numeric IDs
- the server has outbound DNS
- the server can reach Telegram over HTTPS
- no second Hermes gateway is using the same bot token
Published image:
afsharidevops/hermes-smart-router:latest
The Smart Router decides:
What capability tier does this request need?
9router then handles:
Which provider/model should serve that target?
No additional LLM call is required to make the routing decision.
model=auto
│
▼
Smart Router
│
├─ fast → combo-fast
├─ standard → combo-standard
└─ strong → combo-strong
│
▼
9router
Smart Router exposes:
auto
auto-fast
auto-standard
auto-strong
These appear through:
GET /v1/models
Applications can simply request:
{
"model": "auto"
}The Smart Router route-profile defaults depend on the selected backend.
9router (profile 9router):
SMART_ROUTER_FAST_MODEL=combo-fast
SMART_ROUTER_STANDARD_MODEL=combo-standard
SMART_ROUTER_STRONG_MODEL=combo-strongOmniRoute (profile omniroute) uses its auto/best-* aliases instead:
SMART_ROUTER_FAST_MODEL=auto/best-fast
SMART_ROUTER_STANDARD_MODEL=auto/best-chat
SMART_ROUTER_STRONG_MODEL=auto/best-reasoning
SMART_ROUTER_CODING_MODEL=auto/best-coding
SMART_ROUTER_VISION_MODEL=auto/best-visionSMART_ROUTER_MODE=observeRecommended for initial deployment.
Smart Router evaluates automatic requests and records routing observations while preserving the configured observation path.
SMART_ROUTER_MODE=routeAutomatic requests are actively rewritten to the selected tier.
Change mode through the supported management command:
./manage.sh set-router-mode observeor:
./manage.sh set-router-mode route| Tier | Tools | Vision | Context |
|---|---|---|---|
| Fast | No | No | 32k |
| Standard | Yes | No | 128k |
| Strong | Yes | Yes | 200k |
Capability gates take priority over ordinary routing scores.
Default automatic-request budgets:
SMART_ROUTER_FAST_MAX_TOKENS=1024
SMART_ROUTER_STANDARD_MAX_TOKENS=4096
SMART_ROUTER_STRONG_MAX_TOKENS=6144Defaults:
SMART_ROUTER_SESSION_TTL_SECONDS=2700
SMART_ROUTER_MAX_SESSION_AGE_SECONDS=43200
SMART_ROUTER_DEMOTION_TURNS=5These settings reduce unnecessary model/tier switching during conversations.
9router is the provider/model delivery layer for this branch.
Default host dashboard:
http://127.0.0.1:20128
Internal Docker API URL:
http://nine-router:20128/v1
Smart Router must use:
SMART_ROUTER_UPSTREAM_BASE_URL=http://nine-router:20128/v1Never use localhost for Smart Router → 9router communication inside Docker.
Configure your providers and the following default combos in 9router as appropriate:
combo-fast
combo-standard
combo-strong
When Smart Router is enabled, Hermes should use an automatic model and the internal Smart Router endpoint.
Typical effective configuration:
default: auto
base_url: http://smart-router:8080/v1Telegram /model should therefore reflect the automatic routing model rather than a hard-coded provider model.
When Smart Router is enabled, Open WebUI should connect to:
http://smart-router:8080/v1
This gives Open WebUI access to:
auto
auto-fast
auto-standard
auto-strong
as well as upstream models exposed through the router.
Default host port:
http://127.0.0.1:3000
If you intentionally bind Open WebUI to your LAN, restrict the port to trusted networks.
For localhost-only deployment, an SSH tunnel can be used:
ssh -L 3000:127.0.0.1:3000 user@serverThen open:
http://localhost:3000
n8n is optional.
Default port:
127.0.0.1:5678
The stack supports managed n8n MCP integration modes.
Useful commands include:
./manage.sh set-n8n-mcp-mode instance
./manage.sh set-n8n-mcp-mode trigger
./manage.sh set-n8n-mcp-mode off
./manage.sh bootstrap-n8n
./manage.sh reconcile-n8n
./manage.sh verify-n8nFor trigger mode:
./manage.sh rotate-n8n-trigger-tokenFor instance-level MCP authentication:
./manage.sh set-n8n-instance-mcp-tokenInteractive menu:
./manage.sh menuCommon operations:
./manage.sh start
./manage.sh stop
./manage.sh restart
./manage.sh update
./manage.sh status
./manage.sh doctor
./manage.sh configure
./manage.sh uninstallUninstall containers/network but keep configuration and data:
./manage.sh uninstallPermanently purge local stack configuration, runtime data, and secrets (source files and external backups are kept):
./manage.sh uninstall --purgeLogs:
./manage.sh logs
./manage.sh logs hermes
./manage.sh logs 9router
./manage.sh logs smart-router
./manage.sh logs webui
./manage.sh logs n8n
./manage.sh logs caddyRestart Hermes:
./manage.sh restart-hermesChange Smart Router mode:
./manage.sh set-router-mode observe
./manage.sh set-router-mode routeExecution capabilities are disabled until explicitly configured.
Supported capability groups include:
sandbox
ssh
docker
Check state:
./manage.sh execution-statusEnable only what you need:
./manage.sh enable-execution sandbox
./manage.sh enable-execution ssh
./manage.sh enable-execution dockerDisable:
./manage.sh disable-execution sandboxPrivileged execution approval should use a second BotFather bot dedicated to approvals.
Do not reuse the main Hermes Telegram bot.
Configure it with:
./manage.sh set-execution-approval-bot-tokenExecution users must be a subset of the normal Telegram allowlist:
./manage.sh set-execution-users 123456789This keeps routine Telegram chat separate from privileged execution approval.
Hermes Operations Center now includes System → Execution & Approvals. It connects directly from the operator browser to the optional execution-admin service with a separate admin key. The Smart Router backend does not receive that key or the dedicated Telegram approval bot token.
Bootstrap the separate admin boundary:
./manage.sh enable-execution-admin
./manage.sh execution-admin-status
./manage.sh show-execution-admin-keyThe UI can then manage:
- live Sandbox/Docker/SSH feature policy for already-deployed brokers;
- numeric Telegram execution approvers, restricted to
TELEGRAM_ALLOWED_USERS; - write-only replacement of the dedicated approval-bot token;
- broker control-secret rotation;
- broker/approver health and execution-admin audit events;
- redacted SSH profile metadata.
The execution-admin service does not mount the Ed25519 approval signing key, Docker socket, or SSH private credentials. First-time Docker/SSH broker deployment and SSH credential creation/removal remain host manage.sh operations. Port 8752 binds to loopback by default. For remote administration, use a trusted private bind address, TLS/reverse proxy where appropriate, and exact EXECUTION_ADMIN_ALLOWED_ORIGINS; never use wildcard CORS or expose the admin port publicly.
Typical defaults:
| Service | Address |
|---|---|
| 9router | 127.0.0.1:20128 |
| Open WebUI | 127.0.0.1:3000 |
| Hermes API | 127.0.0.1:8642 |
| Hermes dashboard | 127.0.0.1:9119 |
| n8n | 127.0.0.1:5678 |
| Smart Router | Docker network + loopback host binding by default |
Telegram uses outbound polling and does not require an inbound Telegram port.
Persistent runtime data lives beneath:
data/
Important locations include:
data/9router/
data/omniroute/
data/hermes/
data/open-webui/
data/n8n/
data/smart-router/
data/stack-secrets/
Sensitive configuration includes:
.env
data/hermes/.env
data/smart-router/
data/stack-secrets/
Never commit runtime secrets or databases.
The Smart Router runtime directory is intentionally ignored by Git.
The Smart Router container uses a hardened runtime:
- non-root UID
10001 - read-only root filesystem
- dropped capabilities
no-new-privileges- temporary
/tmp - writable runtime
/data - read-only policy mount
smart-router-init prepares the host-backed runtime directory for UID 10001.
Validate Compose:
docker compose \
--env-file .env \
configCheck services:
./manage.sh statusRun diagnostics:
./manage.sh doctorRun Smart Router tests from a development environment:
python -m pip install -e "./smart-router[dev]"
pytest -q smart-router/testsSmart Router v0.5.9 currently passes the repository test suite covering API routing, model aliases, passthrough behavior, SSE preservation, and policy behavior.
From inside the container:
docker exec hermes-smart-router \
python -c 'import urllib.request; print(urllib.request.urlopen("http://127.0.0.1:8080/health").read().decode())'Expected version:
{
"status": "ok",
"version": "0.5.9"
}Inspect aliases:
docker exec hermes-smart-router \
python -c 'import urllib.request; print(urllib.request.urlopen("http://127.0.0.1:8080/v1/models").read().decode())'./manage.sh logs hermesCheck the token, numeric allowlist, outbound network access, and duplicate bot sessions.
The upstream must be:
http://nine-router:20128/v1
docker logs --tail=200 hermes-smart-router./manage.sh logs 9routerVerify:
- Smart Router is healthy.
- 9router has the expected combos/models.
- Open WebUI uses
http://smart-router:8080/v1. - The relevant API key is valid.
afsharidevops/hermes-smart-router:latest
Platforms:
linux/amd64
linux/arm64
OCI release digest:
- Telegram is a first-class Hermes interface.
- Smart Router decides request capability tier.
- The selected router backend (9router or OmniRoute) handles provider/model delivery.
- No extra routing LLM call is required.
- Capability requirements override normal tier scoring.
- Explicit model requests stay explicit.
- Automatic routing uses the selected backend's tier defaults (
combo-*for 9router,auto/best-*aliases for OmniRoute). - Runtime secrets stay outside Git.
- Privileged execution requires explicit enablement and approval.
- The router backend is a profile choice; both backends are maintained on
main.
Branch: main
Smart Router: v0.6.1
Backend: selected by COMPOSE_PROFILES (9router or omniroute)
9router upstream: http://nine-router:20128/v1
OmniRoute upstream: http://omniroute:20129/v1
OmniRoute health: http://omniroute:20128/api/monitoring/health
Fast/standard/strong: combo-* (9router) or auto/best-* (OmniRoute)
Recommended initial router mode: observe
The v0.5.0 release keeps the learned classifier as a proposal layer and preserves deterministic capability, sticky-session, budget, explicit-model, streaming, privacy, and fail-open rules. The safe default remains SMART_ROUTER_MODE=observe with SMART_ROUTER_POLICY=heuristic.
Branch backend: 9router
SMART_ROUTER_UPSTREAM_BASE_URL=http://nine-router:20128/v1
SMART_ROUTER_UPSTREAM_HEALTH_URL=http://nine-router:20128/api/health
SMART_ROUTER_FAST_MODEL=combo-fast
SMART_ROUTER_STANDARD_MODEL=combo-standard
SMART_ROUTER_STRONG_MODEL=combo-strongThe shared v0.5.0 image is afsharidevops/hermes-smart-router:0.5.0. SMART_ROUTER_HMAC_SECRET is mandatory; generate a persistent secret with openssl rand -hex 32 and keep the real value outside Git. Use SMART_ROUTER_*_MAX_CONTEXT for context limits.
For external OpenAI-compatible applications, see docs/SMART-ROUTER-CLIENT-API.md. For standalone TLS or an external Caddy/Nginx/Traefik/other reverse proxy, see docs/SMART-ROUTER-PUBLIC-INGRESS.md.
Learned rollout remains: heuristic+observe → collect safe features → train/evaluate → learned+observe → validate → learned+route. Do not publish cost/quality claims until measured on a representative workload.
See LICENSE.
Third-party images and upstream projects retain their respective licenses.
Smart Router v0.5.9 keeps the built-in measured telemetry dashboard at /dashboard and the authenticated Operations Center at /control/, while preserving 9router as this branch's provider gateway. The Operations Center covers RBAC/users, virtual API keys and quotas, route profiles (fast/standard/strong/coding/vision), provider discovery and provider-health/circuit state, budgets, policies, knowledge/memory, agents/teams, plugins, ACLs, audit events, outcomes, and system state. OIDC and Redis-backed HA are optional advanced settings.
The easy installer now configures the v0.5.9 core switches instead of silently relying on Compose defaults, and ./manage.sh menu exposes a Smart Router submenu. Useful commands include router-status, router-access, router-summary, router-routes, router-provider-health, router-system, router-info, router-policy, router-calibrate, router-report, and router-replay.
Routing semantics are important: Smart Router policy applies to model=auto; auto-fast/auto-standard/auto-strong are available only when tier overrides are enabled. Explicit upstream model names pass through without automatic tier selection. observe evaluates/logs automatic requests but dispatches them through SMART_ROUTER_OBSERVE_MODEL; route applies the selected route profile.
Default local URLs are http://127.0.0.1:8787/v1, http://127.0.0.1:8787/dashboard, and http://127.0.0.1:8787/control/. See docs/HERMES-OPERATIONS-CENTER-USER-GUIDE-v0.5.9.md, docs/RELEASE-PROCESS.md, and smart-router/V0.5.9-RELEASE-NOTES.md for current authentication, OIDC, HA, and release guidance.
Default Smart Router image: afsharidevops/hermes-smart-router:latest; pin SMART_ROUTER_IMAGE_TAG in .env when you want a stable release.
Application images intentionally default to mutable tags so normal docker compose pull tracks upstream releases. You can pin any service later by changing only .env; Compose does not need to be edited.
NINEROUTER_IMAGE_TAG=latest
HERMES_IMAGE_TAG=latest
SMART_ROUTER_IMAGE_TAG=latest
OPENWEBUI_IMAGE_TAG=main
N8N_IMAGE_TAG=latestFor example, replace one or more tag values with a version you have tested, then run:
docker compose --env-file .env pull
docker compose --env-file .env up -d
./manage.sh doctorFor a reproducible snapshot of currently resolved image digests, use ./manage.sh lock-images and ./manage.sh verify-images.
For n8n + Hermes MCP installations, ./install.sh starts n8n first and then offers to finish owner/API/MCP provisioning in the same wizard session. The owner API key and Instance MCP access token remain user-created n8n credentials; the installer validates and stores them through hidden prompts after owner setup. Use ./manage.sh n8n-menu later to inspect status, replace credentials, change MCP mode, reconcile, verify, or rotate the Trigger token. Instance MCP validation follows the stable core tool surface instead of requiring every newer version-gated n8n MCP tool.
Instance-level MCP capabilities are n8n-version-dependent; the stack validates the stable workflow core and does not require newer optional tools such as search_executions just to accept a valid access token.
The visible admin UI is Hermes Operations Center at /control/ (the URL and SMART_ROUTER_CONTROL_* names stay compatible). Knowledge storage is configured server-side so database passwords are not saved in browser state.
Use the same Operations database for RAG knowledge tables:
SMART_ROUTER_CONTROL_DATABASE_URL=postgresql+psycopg://hermes_router:SECRET@postgres:5432/hermes_router
SMART_ROUTER_KNOWLEDGE_DATABASE_URL=Or put knowledge bases/chunks in a separate PostgreSQL database:
SMART_ROUTER_KNOWLEDGE_DATABASE_URL=postgresql+psycopg://hermes_rag:SECRET@rag-postgres:5432/hermes_knowledgeAfter changing the DSN, recreate only Smart Router and inspect Operations Center → Knowledge or ./manage.sh router-system. The UI reports storage mode, connectivity and a redacted DSN. v0.5.9 retains hybrid lexical/vector retrieval, reranking, and PostgreSQL pgvector support from v0.5.6. Configure a real embeddings endpoint for production semantic retrieval.