summary refs log tree commit diff
path: root/modules/agent.nix
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2026-06-14 01:23:23 +0200
committerMel <mel@rnrd.eu>2026-06-14 01:23:23 +0200
commit6e8ba05449304332ad2e94b20c480a95d223ae3b (patch)
tree3488484ec89c7d364ae45e29f19c75563e11a619 /modules/agent.nix
parent2447db440302f2e46123c53af0f05e5d81df4661 (diff)
downloadnetwork-6e8ba05449304332ad2e94b20c480a95d223ae3b.tar.zst
network-6e8ba05449304332ad2e94b20c480a95d223ae3b.zip
Run Renard agent in Hermes harness
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'modules/agent.nix')
-rw-r--r--modules/agent.nix114
1 files changed, 114 insertions, 0 deletions
diff --git a/modules/agent.nix b/modules/agent.nix
new file mode 100644
index 0000000..9cc0636
--- /dev/null
+++ b/modules/agent.nix
@@ -0,0 +1,114 @@
+{ config, hermes-agent, ... }:
+
+{
+  imports = [
+    hermes-agent.nixosModules.default
+  ];
+
+  age.secrets.renard-agent = {
+    file = ../secrets/renard-agent.age;
+    owner = "renard";
+    group = "renard";
+    mode = "0440";
+  };
+
+  services.hermes-agent = {
+    enable = true;
+
+    # the agent has it's own user on the host under
+    # which it runs and can change state at.
+    user = "renard";
+    group = "renard";
+    stateDir = "/home/renard";
+
+    extraDependencyGroups = [ "messaging" ];
+
+    environmentFiles = [
+      # required secrets:
+      # * OPENROUTER_API_KEY
+      # * DISCORD_BOT_TOKEN
+      # * DISCORD_ALLOWED_USERS
+      config.age.secrets.renard-agent.path
+    ];
+
+    settings = {
+      model = {
+        provider = "openrouter";
+        # my current favorite budget model, with recent price
+        # changes by far the cheapest for the performance,
+        # with other chinese models also being close.
+        # only modality is text, requires auxiliary vision model!
+        # native price: $0.44/m in, $0.87/m out.
+        default = "deepseek/deepseek-v4-pro";
+      };
+
+      agent = {
+        reasoning_effort = "high"; # 'high' rated highest in benchmarks, tune to taste!
+        max_turns = 90;
+      };
+
+      auxiliary.vision = {
+        # auxiliary vision model for image comprehension.
+        # this qwen model is built for this exact use-case and is extremely
+        # cheap for the performance (though below gemini), however,
+        # it does not do any reasoning on the visual input!
+        # possible upgrade path for reasoning: qwen3-vl-30b-a3b-thinking
+        # native price: $0.13/m in, $1.56/m out.
+        provider = "openrouter";
+        model = "qwen/qwen3-vl-32b-instruct";
+        timeout = 120;
+      };
+
+      toolsets = [ "all" ];
+
+      terminal = {
+        backend = "local";
+        persistent_shell = true;
+        timeout = 180;
+      };
+
+      memory = {
+        memory_enabled = true;
+        user_profile_enabled = true;
+      };
+
+      # slightly higher limits and targets than default for better
+      # long session preservation.
+      compression = {
+        enabled = true;
+        threshold = 0.75;
+        target_ratio = 0.35;
+        protect_last_n = 40;
+      };
+
+      # progressive message editing, a little silly in discord but looks like
+      # the classic llm chats.
+      streaming = {
+        enabled = true;
+      };
+      display = {
+        streaming = true; # small regression with streaming.enabled, keep both on.
+        tool_progress = "new"; # only show fresh new tool calls, not every call.
+      };
+
+      discord = {
+        require_mention = false;
+        thread_require_mention = false;
+        auto_thread = false;
+        reactions = true;
+        history_backfill = true;
+        allow_mentions = {
+          everyone = false;
+          roles = false;
+          users = true;
+          replied_user = true;
+        };
+      };
+
+      unauthorized_dm_behavior = "ignore"; # ignore strangers
+
+      timezone = "Europe/Berlin";
+      group_sessions_per_user = false;
+    };
+  };
+}