Compare commits

..
Author SHA1 Message Date
william 5507192ee6 Merge pull request 'Add Hermes Agent as a second native Matrix presence' (#10) from feat/hermes-matrix into main
build-agent / build-and-push (push) Successful in 11s
Reviewed-on: #10
2026-08-23 15:49:05 +00:00
william 9fa025f7d5 Add Hermes Agent as a second native Matrix presence
Deployed as its own service (pinned nousresearch/hermes-agent:v2026.8.19),
own Matrix bot account (@hermes), own OpenRouter-backed model config, and
its own OpenAI-compatible API server (internal network only, for possible
future use by claude-agent). Joins the same control room but only responds
when explicitly @mentioned, restricted to the human user — no conflict with
claude-bot's default no-prefix chat routing. claude-agent's router now
ignores messages addressed to @hermes so both bots don't answer the same
message.

Bridge networking (the 'web' network), not the image's default host mode —
no reason for an agent container to share the host's network namespace when
everything it needs (the homeserver, OpenRouter) is reachable over the
existing bridge.
2026-08-23 15:46:58 +00:00
william 5461754f23 Merge pull request 'Route chat through local LiteLLM gateway, drop !claude/!ai prefixes' (#8) from feat/litellm-router into main
build-agent / build-and-push (push) Successful in 7s
Reviewed-on: #8
2026-08-23 15:34:29 +00:00
3 changed files with 42 additions and 0 deletions
+11
View File
@@ -40,6 +40,17 @@ OPENROUTER_API_KEY=
# Any random string; also used as litellm's general_settings.master_key. # Any random string; also used as litellm's general_settings.master_key.
LITELLM_MASTER_KEY= LITELLM_MASTER_KEY=
# --- hermes (autonomous agent with its own native Matrix presence) ---
# Your own Matrix ID — Hermes only responds to this user, and only when @mentioned
# in a shared room (e.g. "@hermes <task>" in the control room).
MATRIX_HUMAN_USER_ID=@william:matrix.apps.williamturner.eu
# Access token for the @hermes bot account (register it the same way as claude-bot —
# see README — then log in as it via /_matrix/client/v3/login to get this token).
HERMES_MATRIX_ACCESS_TOKEN=
# Any random string — bearer key for Hermes's own OpenAI-compatible API server
# (internal network only, not published anywhere).
HERMES_API_SERVER_KEY=
# --- portainer (GitOps redeploy) --- # --- portainer (GitOps redeploy) ---
PORTAINER_STACK_WEBHOOK_URL= PORTAINER_STACK_WEBHOOK_URL=
+4
View File
@@ -49,6 +49,10 @@ export async function startMatrixBot() {
if (event.sender === BOT_USER_ID) return; if (event.sender === BOT_USER_ID) return;
const body = event.content?.body; const body = event.content?.body;
if (!body) return; if (!body) return;
// Messages explicitly addressed to another agent in this room (currently just
// @hermes) are that agent's to answer — without this, claude-bot's classifier would
// also see and reply to them, since it otherwise treats every message as its own.
if (/^@hermes\b/i.test(body.trim())) return;
try { try {
const decision = await routeMessage(body, KNOWN_REPOS); const decision = await routeMessage(body, KNOWN_REPOS);
+27
View File
@@ -61,6 +61,33 @@ services:
# Internal only — no Traefik labels. No reason to expose an LLM gateway holding a # Internal only — no Traefik labels. No reason to expose an LLM gateway holding a
# master key and OAuth-forwarding config to the public internet. # master key and OAuth-forwarding config to the public internet.
hermes:
# Pinned to a specific dated release, not :latest — same rationale as litellm above.
image: nousresearch/hermes-agent:v2026.8.19
container_name: hermes
restart: unless-stopped
environment:
HERMES_UID: "1000"
HERMES_GID: "1000"
# Internal container address, not the public HTTPS one — same docker network as
# matrix-homeserver, no reason to round-trip through Traefik/TLS for this.
MATRIX_HOMESERVER: http://matrix-homeserver:8008
MATRIX_ACCESS_TOKEN: ${HERMES_MATRIX_ACCESS_TOKEN}
# Only you can trigger it; and only with an explicit @hermes mention in shared
# rooms (DMs to it would respond unprompted, per Hermes's own default behavior).
MATRIX_ALLOWED_USERS: ${MATRIX_HUMAN_USER_ID}
MATRIX_REQUIRE_MENTION: "true"
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY}
# Exposed on the internal network only (see claude-agent's LITELLM_BASE_URL-style
# usage pattern) — nothing publishes this port externally.
API_SERVER_ENABLED: "true"
API_SERVER_HOST: 0.0.0.0
API_SERVER_KEY: ${HERMES_API_SERVER_KEY}
volumes:
- /home/william/hermes-data:/opt/data
networks:
- web
claude-agent: claude-agent:
image: ${GITEA_REGISTRY_IMAGE} image: ${GITEA_REGISTRY_IMAGE}
depends_on: depends_on: