feat(nix): add #messaging and #full package variants (#33108)

* fix(plugins/discord): correct install_hint extra to [messaging]

The Discord platform registered install_hint pointing at
'hermes-agent[discord]', but pyproject.toml has no [discord] extra —
the deps live in [messaging] alongside Telegram and Slack. Users hitting
"Platform 'Discord' requirements not met" were directed at a pip command
that installs nothing.

* feat(nix): add #messaging and #full package variants

Make Discord/Telegram/Slack work out of the box for `nix profile install`
users. Messaging deps were dropped from [all] on 2026-05-12 in favor of
lazy-install, but lazy-install can't write to the read-only /nix/store —
users hit "No adapter available for discord" with no actionable guidance.

  - #messaging: pre-built with discord.py/telegram/slack (+33 MB venv)
  - #full:      all 18 platform-portable extras + matrix on Linux only
                (python-olm lacks Darwin PyPI wheels) (+738 MB venv)

Also adds a `messaging-variant` flake check that verifies `import discord`
succeeds in the sealed venv — regression guard for the lazy-install
migration.

Docs updated: Quick Start callout, extraDependencyGroups rewrite with
messaging as primary example + full extras table, troubleshooting row,
cheatsheet row.

Closure size deltas (measured x86_64-linux):
  default   1792 MB pkg / 512 MB venv
  messaging 1826 MB pkg / 546 MB venv   (+33 MB)
  full      2530 MB pkg / 1250 MB venv  (+738 MB)

* chore(nix): trim variant comments + alphabetize full extras

Drop the date-stamped changelog from messaging-variant's comment and the
"+33 MB / +704 MB" numbers from the variant defs — those drift and belong
in the PR description, not source. Alphabetize the 18-extra list in #full
so future additions produce clean one-line diffs.

No semantic change. messaging-variant check still passes.
This commit is contained in:
Siddharth Balyan 2026-05-27 14:15:39 +05:30 committed by GitHub
parent 25f43d38de
commit 976979489a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 96 additions and 4 deletions

View file

@ -260,6 +260,19 @@ json.dump(sorted(leaf_paths(DEFAULT_CONFIG)), sys.stdout, indent=2)
echo "ok" > $out/result
'';
# Regression guard: messaging deps live outside [all], so the
# #messaging variant must actually ship discord.py — otherwise
# `nix profile install .#messaging` regresses to the broken default.
messaging-variant = pkgs.runCommand "hermes-messaging-variant" { } ''
set -e
echo "=== Checking discord.py importable from messaging variant ==="
${self'.packages.messaging.hermesVenv}/bin/python3 -c \
"import discord; print(discord.__version__)"
echo "PASS: discord.py importable from messaging variant venv"
mkdir -p $out
echo "ok" > $out/result
'';
# ── Config merge + round-trip test ────────────────────────────────
# Tests the merge script (Nix activation behavior) across 7
# scenarios, then verifies Python's load_config() reads correctly.

View file

@ -2,7 +2,7 @@
{ inputs, ... }:
{
perSystem =
{ pkgs, inputs', ... }:
{ pkgs, lib, inputs', ... }:
let
hermesAgent = pkgs.callPackage ./hermes-agent.nix {
inherit (inputs) uv2nix pyproject-nix pyproject-build-systems;
@ -15,6 +15,39 @@
{
packages = {
default = hermesAgent;
# Ships discord.py + python-telegram-bot + slack-sdk so a plain
# `nix profile install .#messaging` connects to Discord/Telegram/Slack
# on first run — lazy-install can't write to the read-only /nix/store.
messaging = hermesAgent.override {
extraDependencyGroups = [ "messaging" ];
};
# All platform-portable optional integrations pre-built.
# matrix is Linux-only (oqs/liboqs lacks aarch64-darwin wheels).
full = hermesAgent.override {
extraDependencyGroups = [
"anthropic"
"azure-identity"
"bedrock"
"daytona"
"dingtalk"
"edge-tts"
"exa"
"fal"
"feishu"
"firecrawl"
"hindsight"
"honcho"
"messaging"
"modal"
"parallel-web"
"tts-premium"
"vercel"
"voice"
] ++ lib.optionals pkgs.stdenv.isLinux [ "matrix" ];
};
tui = hermesAgent.hermesTui;
web = hermesAgent.hermesWeb;

View file

@ -6163,7 +6163,7 @@ def register(ctx) -> None:
check_fn=check_discord_requirements,
is_connected=_is_connected,
required_env=["DISCORD_BOT_TOKEN"],
install_hint="pip install 'hermes-agent[discord]'",
install_hint="pip install 'hermes-agent[messaging]'",
# Interactive setup wizard — replaces the central
# hermes_cli/setup.py::_setup_discord function. Same shape as Teams.
setup_fn=interactive_setup,

View file

@ -46,6 +46,22 @@ hermes chat
After `nix profile install`, `hermes`, `hermes-agent`, and `hermes-acp` are on your PATH. From here, the workflow is identical to the [standard installation](./installation.md) — `hermes setup` walks you through provider selection, `hermes gateway install` sets up a launchd (macOS) or systemd user service, and config lives in `~/.hermes/`.
:::warning Messaging platforms (Discord, Telegram, Slack)
The default package doesn't include messaging platform libraries — they were moved to on-demand installation, which can't work in Nix's read-only environment. If you plan to connect the agent to Discord, Telegram, or Slack, install the `messaging` variant:
```bash
nix profile install github:NousResearch/hermes-agent#messaging
```
For all optional extras (voice, all providers, all platforms):
```bash
nix profile install github:NousResearch/hermes-agent#full
```
The `full` variant adds ~700 MB to the closure. If you only need messaging platforms, `#messaging` adds just ~33 MB.
:::
<details>
<summary><strong>Building from a local clone</strong></summary>
@ -319,6 +335,7 @@ Quick reference for the most common things Nix users want to customize:
| Add API keys | `environmentFiles` | `[ config.sops.secrets."hermes-env".path ]` |
| Give the agent a personality | `${services.hermes-agent.stateDir}/.hermes/SOUL.md` | manage the file directly |
| Add MCP tool servers | `mcpServers.<name>` | See [MCP Servers](#mcp-servers) |
| Enable Discord/Telegram/Slack | `extraDependencyGroups` | `[ "messaging" ]` |
| Mount host directories into container | `container.extraVolumes` | `[ "/data:/data:rw" ]` |
| Pass GPU access to container | `container.extraOptions` | `[ "--gpus" "all" ]` |
| Use Podman instead of Docker | `container.backend` | `"podman"` |
@ -647,16 +664,44 @@ The package's `site-packages` is added to PYTHONPATH in the hermes wrapper. `imp
### Optional Dependency Groups (`extraDependencyGroups`)
For optional extras already declared in hermes-agent's `pyproject.toml` (e.g., memory providers like `hindsight` or `honcho`), use `extraDependencyGroups` to include them in the sealed venv at build time:
For optional extras declared in hermes-agent's `pyproject.toml`, use `extraDependencyGroups` to include them in the sealed venv at build time. This is required for any extra not in the default `[all]` set — on Nix, runtime installation into the read-only store is not possible.
```nix
# Enable Discord, Telegram, Slack
services.hermes-agent.extraDependencyGroups = [ "messaging" ];
```
```nix
# Enable a memory provider
services.hermes-agent = {
extraDependencyGroups = [ "hindsight" ];
settings.memory.provider = "hindsight";
};
```
This is resolved by uv alongside core dependencies in a single pass — no PYTHONPATH patching, no collision risk. Available groups match the `[project.optional-dependencies]` keys in `pyproject.toml` (e.g., `"hindsight"`, `"honcho"`, `"voice"`, `"matrix"`, `"mistral"`, `"bedrock"`).
This is resolved by uv alongside core dependencies — no PYTHONPATH patching, no collision risk. Available groups:
| Group | What it enables |
|-------|-----------------|
| `messaging` | Discord, Telegram, Slack |
| `matrix` | Matrix/Element (mautrix with encryption; Linux only) |
| `dingtalk` | DingTalk |
| `feishu` | Feishu/Lark |
| `voice` | Local speech-to-text (faster-whisper) |
| `edge-tts` | Edge TTS provider |
| `tts-premium` | ElevenLabs TTS |
| `anthropic` | Native Anthropic SDK (not needed via OpenRouter) |
| `bedrock` | AWS Bedrock (boto3) |
| `azure-identity` | Azure Entra ID auth |
| `honcho` | Honcho memory provider |
| `hindsight` | Hindsight memory provider |
| `modal` | Modal terminal backend |
| `daytona` | Daytona terminal backend |
| `exa` | Exa web search |
| `firecrawl` | Firecrawl web search |
| `fal` | FAL image generation |
Or use the pre-built `#messaging` or `#full` flake packages instead of per-extra configuration (see [Quick Start](#quick-start-any-nix-user)).
**When to use which:**
@ -966,6 +1011,7 @@ nix-store --query --roots $(docker exec hermes-agent readlink /data/current-pack
| Symptom | Cause | Fix |
|---|---|---|
| `Cannot save configuration: managed by NixOS` | CLI guards active | Edit `configuration.nix` and `nixos-rebuild switch` |
| `No adapter available for discord` (or telegram/slack) | Messaging deps missing from the sealed Nix venv | Install `#messaging` variant: `nix profile install ...#messaging`. For NixOS module: `extraDependencyGroups = [ "messaging" ]`. Check `journalctl -u hermes-agent` for `FeatureUnavailable` or `requirements not met` for the underlying error. |
| Container recreated unexpectedly | `extraVolumes`, `extraOptions`, or `image` changed | Expected — writable layer resets. Reinstall packages or use a custom image |
| `hermes version` shows old version | Container not restarted | `systemctl restart hermes-agent` |
| Permission denied on `/var/lib/hermes` | State dir is `0750 hermes:hermes` | Use `docker exec` or `sudo -u hermes` |