Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

AI Agent — Hermes Autonomous Agent

Purpose

Autonomous AI Agent service powered by Hermes, providing intelligent task automation with security controls for code review and development tasks.

Entry Point

  • Main file: ai-agent.nix
  • Upstream: Hermes Agent
  • Package: The module routes services.hermes-agent.package through the local pkgs.hermes-agent overlay, which carries a few upstream patches.

Options

services.ai-agent.apiServer.enable

Typeboolean
Defaultfalse
Exampletrue

Whether to enable the OpenAI comptable endpoint.


services.ai-agent.apiServer.host

Typestring
Default"127.0.0.1"

The host/IP for the API server to bind to.


services.ai-agent.apiServer.port

Typesigned integer
Default8642

The port for the API server to listen on.


services.ai-agent.apiServer.tokenReference

Typestring
Default"AI_AGENT/API_SERVER_TOKEN"

The sops secret attribute for the API server authentication token.


services.ai-agent.containerPostStart

Typelist of (string or (submodule))
Default[ ]

Shell commands to run inside the AI agent container after startup.

A plain string runs inside the container as root via docker exec. An attrset { command = "..."; host = true; } runs on the host.

Commands to run after the AI agent container starts. Container commands get automatic retry to wait for Docker + container readiness.


services.ai-agent.dashboard.enable

Typeboolean
Defaultfalse
Exampletrue

Whether to enable Hermes web dashboard.


services.ai-agent.dashboard.oidc.clientId

Typestring

The OIDC client ID for dashboard authentication.


services.ai-agent.dashboard.oidc.enable

Typeboolean
Defaultfalse
Exampletrue

Whether to enable OpenID Connect authentication for the dashboard.


services.ai-agent.dashboard.oidc.issuer

Typestring

The OIDC issuer URL for dashboard authentication.


services.ai-agent.dashboard.oidc.provider

Typestring
Default"self-hosted"

The OIDC plugin to use for dashboard authentication.


services.ai-agent.dashboard.oidc.scopes

Typelist of string
Default[ "openid" "profile" "email" ]

The OIDC scopes to request for dashboard authentication.


services.ai-agent.dashboard.port

Typesigned integer
Default9119

The port for the dashboard to listen on.


services.ai-agent.dashboard.publicURL

Typenull or string
Defaultnull

The public URL for the dashboard, used for generating links in notifications and similar. If not set, localhost URLs will be used.

If set, must be a valid URL starting with http:// or https://.


services.ai-agent.enable

Typeboolean
Defaultfalse
Exampletrue

Whether to enable autonomous AI Agent service.


services.ai-agent.extras.browser

Typeboolean
Defaultfalse
Exampletrue

Whether to enable headless browser for web scraping and automation.


services.ai-agent.extras.plugins

Typeboolean
Defaultfalse
Exampletrue

Whether to enable extra plugins for the agent.


services.ai-agent.extras.scraper.enable

Typeboolean
Defaultfalse
Exampletrue

Whether to enable web scraping and search plugins for the agent.


services.ai-agent.extras.scraper.searxEndpoint

Typenull or string
Defaultnull

The SearxNG endpoint to use for web search.


services.ai-agent.memory.enable

Typeboolean
Defaultfalse
Exampletrue

Whether to enable long-term memory

When enabled this disables the builtin user profile and memory markdown features, to nudge the agent towards using the configured long-term memory provider for all memory. .


services.ai-agent.models.brains

Typestring
Default"deepseek/deepseek-v4-pro-0813"

The smartest model to use for complex reasoning and decision-making tasks.

Used for auxiliary models:


services.ai-agent.models.compression

Typestring
Default"~deepseek/deepseek-v4-flash-latest"

The model to use for compression of context, summorisation and similar tasks that don’t require reasoning. This model still needs a decently sized context window to be effective.

Used for auxiliary models:


services.ai-agent.models.primary

Typestring
Default"~deepseek/deepseek-v4-flash-latest"

The primary language model to use for the AI agent.


services.ai-agent.models.provider

Typestring
Default"openrouter"

The model provider to use.


services.ai-agent.models.simpleton

Typestring
Default"inclusionai/ling-3.0-flash"

The simpleton model to delegate tasks to that require less reasoning, basic understanding and small context windows.

Used for auxiliary models:


services.ai-agent.models.vision

Typestring
Default"xiaomi/mimo-v2.5"

The vision model to delegate image understanding tasks to.


services.ai-agent.platform.discord.allowedUsers

Typelist of string
Default[ ]

A list of Discord user IDs that the agent is allowed to interact with.


services.ai-agent.platform.discord.enable

Typeboolean
Defaultfalse
Exampletrue

Whether to enable Discord as a messaging channel.


services.ai-agent.platform.discord.homeChannel

Typenull or string
Defaultnull

The Discord channel ID to use as the home channel for the agent.


services.ai-agent.platform.discord.tokenReference

Typestring
Default"AI_AGENT/DISCORD_BOT_TOKEN"

The sops secret attribute for the Discord bot token.


services.ai-agent.platform.hassio.enable

Typeboolean
Defaultfalse
Exampletrue

Whether to enable Home Assistant as a tool and notification channel.


services.ai-agent.platform.hassio.tokenReference

Typestring
Default"AI_AGENT/HASSIO_TOKEN"

The sops secret attribute for the Home Assistant long-lived access token.


services.ai-agent.platform.hassio.url

Typestring

The URL for the Home Assistant instance, including the scheme.


services.ai-agent.platform.webhook.port

Typesigned integer
Default8654

The port for the webhook listener to listen on.


services.ai-agent.settings

TypeHermes config attrs, deep-merged with list concatenation.
Default{ }

Hermes config to merge into services.hermes-agent.settings.

This is a local option that merges correctly across feature toggles. The upstream services.hermes-agent.settings uses lib.recursiveUpdate for its config type, which replaces lists instead of concatenating them, so separate blocks would clobber each other. This option deep-merges with list concatenation and is emitted once as the final value of services.hermes-agent.settings.


services.ai-agent.voice.enable

Typeboolean
Defaultfalse
Exampletrue

Whether to enable voice input and output using the TTS and STT.


services.ai-agent.voice.wyoming-stt.enable

Typeboolean
Defaultfalse
Exampletrue

Whether to enable use existing Wyoming faster-whisper server for STT instead of running a separate Whisper instance.


services.ai-agent.voice.wyoming-stt.host

Typestring
Default"localhost"

The host of the Wyoming faster-whisper server.


services.ai-agent.voice.wyoming-stt.port

Typesigned integer
Default10300

The port of the Wyoming faster-whisper server.


Architecture / Services / Scope

The module enables services.hermes-agent (running inside a Docker container) and adds optional components on top:

  • Dashboard — a separate hermes-dashboard systemd service runs docker exec into the hermes-agent container to serve the dashboard under the hermes user. Environment files configured via services.hermes-agent.environmentFiles are loaded by systemd’s EnvironmentFile directive (read as root) and passed into the container via docker exec --env-file. The dashboard stays local by default and does not open a browser.
  • Voice & STT — optional voice input and output. With services.ai-agent.voice.wyoming-stt.enable, Hermes reuses an existing Wyoming faster-whisper server instead of running a separate Whisper instance: HERMES_LOCAL_STT_COMMAND is set to invoke wyoming-transcribe, which sends audio over the Wyoming protocol and returns the transcript. No second Whisper process needed.
  • OIDC Authentication — optional OpenID Connect authentication for the dashboard using a public PKCE client (no client_secret). The client ID is a public identifier — it does not need to be stored as a secret. The module generates a HERMES_DASHBOARD_OIDC_ENV environment file with the OIDC settings, loaded by the hermes-dashboard service.
  • Memory (Mnemosyne) — with services.ai-agent.memory.enable, the memory provider switches from the built-in user profile (USER.md injection) to Mnemosyne, a local SQLite-backed memory system with semantic recall (SQLite with FTS5 hybrid ranking + vector search).

Secrets

Hermes requires API keys via environment files. Configure via sops-nix:

sops = {
  secrets = {
    "AI_AGENT/OPENROUTER_API_KEY" = { };
  };
  templates."HERMES_ENV".content = ''
    OPENROUTER_API_KEY=${config.sops.placeholder."AI_AGENT/OPENROUTER_API_KEY"}
  '';
};

services.hermes-agent.environmentFiles = [ config.sops.templates."HERMES_ENV".path ];

The module itself declares secrets for the enabled optional components:

  • API server token (default AI_AGENT/API_SERVER_TOKEN) — authenticates the OpenAI-compatible API server.
  • Discord bot token (default AI_AGENT/DISCORD_BOT_TOKEN) — Discord platform.
  • Home Assistant token (default AI_AGENT/HASSIO_TOKEN) — Home Assistant platform.
  • Dashboard OIDC uses a public PKCE client, so no client secret is stored.

Operational Notes / Assumptions

Usage Example

{ ... }: {
  services.ai-agent = {
    enable = true;
  };
}

Voice & STT

Enable voice input and output with services.ai-agent.voice.enable = true;. To reuse an existing Wyoming faster-whisper server instead of running a separate Whisper instance:

{ ... }: {
  services.ai-agent = {
    enable = true;
    voice = {
      enable = true;
      wyoming-stt.enable = true;
    };
  };
}

Dashboard & OIDC

Enable the web dashboard with services.ai-agent.dashboard.enable = true;, and OIDC authentication with services.ai-agent.dashboard.oidc.enable = true;:

{ ... }: {
  services.ai-agent = {
    enable = true;
    dashboard = {
      enable = true;
      publicURL = "https://dashboard.example.com";
      oidc = {
        enable = true;
        provider = "self-hosted";
        issuer = "https://auth.example.com/oauth2/openid/hermes";
        clientId = "hermes";
        scopes = [ "openid" "profile" "email" ];
      };
    };
  };
}

Memory (Mnemosyne)

Enable long-term memory with services.ai-agent.memory.enable = true;:

{ ... }: {
  services.ai-agent = {
    enable = true;
    memory.enable = true;
  };
}

References