sokrates-ctl CLI and Hermes Agent Integration

Summary

This cluster documents the sokrates-ctl diagnostic CLI and its evolution from the original nix-openclaw plugin contract to the current Hermes Agent integration. The CLI (sokrates-ctl) remains a thin Python tool for stack diagnostics and message bridging. The nix-openclaw plugin contract that originally drove its design has been superseded by the nix-hermes NixOS module, which provides native Hermes Agent integration with declarative configuration, channel management, and secret injection.

Details

Historical Context: nix-openclaw Plugin Contract

The original architecture made Sokrates a nix-openclaw plugin, with a flake output exposing an openclawPlugin attrset (name, skills paths, packages, stateDirs, requiredEnv). This was driven by two goals: solving the WhatsApp channel issue at the right layer and producing a composable flake output for fleet machines. During this period, a nix-openclaw packaging bug (issue 83) prevented plugin manifests from loading, requiring the flake input to be pinned to a PR #81 fork branch. These issues became moot with the migration to Hermes Agent.

Current Architecture: nix-hermes Integration

The communication layer is now handled by Hermes Agent via the nix-hermes NixOS module. Hermes is configured declaratively in nixos/modules/hermes.nix, which deep-merges settings into ~/.hermes/config.yaml. Channel credentials and API keys are managed through a sops-injected secrets file at /var/lib/sokrates/secrets/hermes/hermes.env.

The flake at repo root now exposes:

  • packages.x86_64-linux.sokrates-ctl — the diagnostic CLI Nix derivation
  • nixosConfigurations.* — fleet images consuming the nix-hermes flake input

sokrates-ctl CLI

plugin/cli/ is a standalone Python package intentionally excluded from the root uv workspace, since it runs on the NixOS host rather than in containers. Dependencies are minimal: httpx, typer, pydantic-settings. The entry point is sokrates-ctl.

Three subcommands:

  • sokrates-ctl send --message "..." --channel slack --from user123 — POSTs to the Hermes Agent at localhost:8080/api/v1/messages
  • sokrates-ctl health — checks Neo4j, Eidos, and Hermes Agent health endpoints; exits with code 1 if any service is down
  • sokrates-ctl query --question "..." — direct Eidos knowledge graph query

Configuration is handled by a Settings class via pydantic-settings with the SOKRATES_ env prefix. Key fields: pk_url (default http://localhost:8080), eidos_url, auth_file, log_level. An auth_token() method reads a bearer token from auth_file if configured, returning None gracefully for missing files.

The SokratesClient class wraps httpx calls with proper error handling — health checks degrade gracefully on connection errors and non-200 responses rather than raising. All CLI output is JSON for machine parseability.

The package ships 16 tests across test_config.py (defaults, env overrides, auth token reading) and test_client.py (send, health variants, query) using pytest-httpx for HTTP mocking. The Nix derivation uses buildPythonApplication with Python 3.13 and hatchling as the build system.

Skills

Three SKILL.md files in plugin/skills/ define Claude Code-discoverable skills:

  • ask-sokrates/SKILL.md — primary message routing, calls sokrates-ctl send
  • query-eidos/SKILL.md — knowledge graph queries, calls sokrates-ctl query
  • sokrates-health/SKILL.md — stack health check, calls sokrates-ctl health

plugin/AGENTS.md documents all env vars, state directories, service dependencies, and an example Nix config block for fleet consumption.

Justfile Integration

Four plugin tasks were appended to the root Justfile: plugin-build (nix build), plugin-test (pytest in plugin/cli/), plugin-lint (ruff check + format check), and plugin-health (live stack health via sokrates-ctl health).