summaryrefslogtreecommitdiff
path: root/modules/foundation
diff options
context:
space:
mode:
Diffstat (limited to 'modules/foundation')
-rw-r--r--modules/foundation/agent.nix196
-rw-r--r--modules/foundation/default.nix1
2 files changed, 197 insertions, 0 deletions
diff --git a/modules/foundation/agent.nix b/modules/foundation/agent.nix
new file mode 100644
index 0000000..6ac25aa
--- /dev/null
+++ b/modules/foundation/agent.nix
@@ -0,0 +1,196 @@
+{
+ config,
+ pkgs,
+ lib,
+ hermes-agent,
+ ...
+}:
+
+let
+ inherit (lib) mkEnableOption mkIf mkMerge;
+ cfg = config.foundation.agent;
+
+ # the set of tools the agent has access to by default.
+ # it should also always be able to call `nix-shell` to gain access to more tools.
+ agentPackages = with pkgs; [
+ nix
+ nixfmt-rfc-style
+
+ openssh
+ tailscale
+
+ docker_29
+
+ jq
+ yq-go
+ ripgrep
+ fd
+ tree
+ file
+ unzip
+ gnused
+ gawk
+
+ curl
+ wget
+
+ htop
+ glances
+ lsof
+ iproute2
+ iputils
+ inetutils
+
+ dig
+ tcpdump
+ nmap
+
+ git
+
+ vim
+ ];
+in
+{
+ imports = [
+ hermes-agent.nixosModules.default
+ ];
+
+ options.foundation.agent = {
+ home = mkEnableOption "the 'renard' agent to live on this machine";
+ neighbor = mkEnableOption "letting the 'renard' agent access this machine";
+ };
+
+ config = mkMerge [
+ # both the home and each neighbor have a user for the agent.
+ (mkIf (cfg.home || cfg.neighbor) {
+ users = {
+ groups.renard = { };
+
+ users.renard = {
+ isSystemUser = true;
+ group = "renard";
+ home = "/home/renard";
+ createHome = true;
+ shell = pkgs.bashInteractive;
+ packages = agentPackages;
+ };
+ };
+ })
+
+ # the agent lives at home.
+ (mkIf cfg.home {
+ age.secrets.renard-agent = {
+ file = ../../secrets/renard-agent.age;
+ owner = "renard";
+ group = "renard";
+ mode = "0440";
+ };
+
+ services.hermes-agent = {
+ enable = true;
+
+ user = "renard";
+ group = "renard";
+ stateDir = "/home/renard";
+ createUser = false;
+
+ extraDependencyGroups = [ "messaging" ];
+
+ # both the user and the path house the same package set
+ extraPackages = agentPackages;
+
+ environmentFiles = [
+ # required secrets:
+ # * OPENROUTER_API_KEY
+ # * DISCORD_BOT_TOKEN
+ # * DISCORD_ALLOWED_USERS
+ config.age.secrets.renard-agent.path
+ ];
+
+ documents = {
+ "SOUL.md" = ../../assets/agent/SOUL.md;
+ };
+
+ 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;
+ };
+ };
+ })
+ ];
+}
diff --git a/modules/foundation/default.nix b/modules/foundation/default.nix
index fa84750..558f80a 100644
--- a/modules/foundation/default.nix
+++ b/modules/foundation/default.nix
@@ -7,5 +7,6 @@
./monitoring
./www
./vpn.nix
+ ./agent.nix
];
}