ollama-hermes-config
Ollama + Hermes Agent + Home Assistant (CT 103, michelle-ollama)
Local, zero-cost AI agents on 192.168.1.139 (an unprivileged LXC on the Proxmox host michelle, 192.168.1.96): Home Assistant control and speech, a website developer, and a notes keeper with long-term memory.
Stack
- Ollama 0.40 serving
qwen38-27b-32k(Qwen3.8 27B, 2-bit text-only GGUF, 32K context, 7.9 GB, 100% on the RTX 3080, about 40 tokens/s).qwen3-8b-64k(Qwen3 8B) is kept as a fallback. See modelfiles/. - Hermes Agent v0.21.5 (source install) at /usr/local/lib/hermes-agent, with three profiles: Nabu, Dev, Nisaba (below)
- Hindsight 1.0.0 memory server on 127.0.0.1:8888 (systemd/hindsight.service), used by Nisaba only
- wyoming-piper at /opt/piper, port 10200, voice en_GB-alba-medium
- Home Assistant at 192.168.1.169:8123 (separate Raspberry Pi)
- Obsidian vault: /srv/vault on CT 103 is /georgia/media/notes on the host, shared with Nextcloud (VM 206, 192.168.1.180) over NFS
Agents
| Profile | Start with | Job |
|---|---|---|
| Nabu (default profile) | nabu chat |
Home Assistant and the household. Tools: the home MCP server (bin/home-tools-mcp: make_web_page, fix_web_page, speak and others), vault reader tools, ask_nisaba. Built-in memory only. |
| Dev | dev chat |
Develops keateswebsite (start_task, check, show_changes, deploy_dev, release_notes, release_prod). Tools: bin/dev-tools-mcp, vault reader tools, ask_nisaba. |
| Nisaba | nisaba chat |
Keeps the Obsidian vault; the only agent with Hindsight memory. Tools: vault MCP server in keeper mode. No shell, no web. |
All three use the same 27B and llama-server has a single slot, so only one model turn runs at a time. Start chats from ~, not inside a repo.
Non-obvious decisions
- Do not use Hermes 3/4 models as the agent brain. Nous' own Hermes models are not agentic and cannot emit tool calls. The name is a trap.
tools.tool_search.enabled: offin config.yaml (all profiles). By default Hermes hides real tools behind a tool_search/tool_describe/tool_call dispatcher, and a small model cannot build the nested payload and loops forever.MINIMUM_CONTEXT_LENGTHis patched to 32_000 in agent/model_metadata.py (about line 272; upstream hardcoded 64_000 as of v0.21.3, with no config override), so the 27B's 32K window is accepted.hermes updatestashes and restores this: answer Y to "Restore local changes". See patches/.- A tool present in the schema beats a prompt telling the model not to use it. Capability must be removed, not discouraged. Home Assistant is driven by wrapper scripts (bin/ha-do, ha-entities, say), not the homeassistant toolset. Nisaba has no terminal and no delete tool for the same reason.
- Speech goes through the home MCP
speaktool, which runs bin/say. The older path unit say-watch.path (watches /tmp/msg.txt, say-file speaks it then deletes it) is still in systemd/. - Long file content never goes through a tool-call argument. The 27B garbles kilobytes of HTML inside JSON, so make_web_page calls bin/gen-file, which asks Ollama directly and writes the file.
- Piper runs here, not on the Pi. Cold synthesis on the Pi took 22.7 s per sentence and the Sonos timed out. Locally: 0.68 s after pinning CT 103 to cpuset 8-11 (the default
cores: 4gave a fragmented 2,5-6,10 and onnxruntime could not pin threads). - systemd/ollama-override.conf must keep
OLLAMA_HOST=0.0.0.0:11434(Home Assistant connects to it). Edit it with sed or nano, never overwrite it wholesale. It also caps llama-server's prompt cache (LLAMA_ARG_CACHE_RAM=1024) and checkpoints (LLAMA_ARG_CTX_CHECKPOINTS=3) and setsOLLAMA_KEEP_ALIVE=30m, after the host ran out of memory on 2026-10-08. - Memory is Nisaba's job. Hindsight is wired to Nisaba only (bank
nisaba, hybrid mode, automatic recall on, automatic saving off). Saving every turn stored the assistant's wrong answers as facts, and a small model's "Noted" is not proof, so saves are explicit tool calls and checked in the log. Nabu and Dev reach her throughask_nisabaand the vault tools. - The vault is one folder shared three ways. Nextcloud reads it through an NFS bind-mount export with
all_squashandfsid=101, so Nextcloud and CT 103 write as the same owner. A plain sub-export would not squash. Vault directories stay 2755 and files 644.
Nightly jobs (CT 103, UTC)
- 03:30
file-inbox.timer: files notes waiting in the vault Inbox. The model only picks a folder and a name; the script does the move. - 03:45
repo-sync.timer: mirrors the READMEs of the Gitea projects into the vault (Projects/) and keeps the Recent changes block at the end of each README up to date through a pull request from thenisabauser. Do not edit between thenisaba:changesmarkers; edit anything else freely.
Files
- bin/ - scripts and MCP servers (say, say-file, ha-do, ha-entities, random-fact, weather-brief, gen-file, check-page, home-tools-mcp, dev-tools-mcp, and the vault wrappers); install to /usr/local/bin
- vault-tools/ - the vault MCP server, the ask_nisaba bridge, file-inbox and repo-sync (install with vault-tools/install.sh)
- systemd/ - wyoming-piper, wyoming-whisper, say-watch, weather-hook, site-serve, hermes-serve, hindsight, file-inbox and repo-sync units, and the Ollama override
- hermes/ - Nabu's config.yaml, SOUL.md, MEMORY.md, env.example
- hermes-dev/ - the Dev profile's config.yaml and SOUL.md
- hermes-nisaba/ - the Nisaba profile's config.yaml and SOUL.md, hindsight-config.json, hindsight.env.example, nisaba-repos.json
- modelfiles/ - Ollama Modelfiles (qwen38-27b-32k, qwen3-8b-64k)
- patches/ - the local Hermes patches
- site/, site-descriptions/ - pages built by make_web_page and the descriptions they were built from (served by site-serve.service on :8080)
- sync.sh - re-capture live state into this repo
Secrets
Nothing secret is committed. /root/.hermes/.env holds HASS_TOKEN and is gitignored; hermes/env.example is the redacted template. The Gitea token that repo-sync uses lives in /root/.config/nisaba/git-credentials, outside this repo. hermes-nisaba/hindsight.env.example is a redacted copy of /etc/hindsight.env.
Recent changes
- 2026-10-15
3cb4f89Capture Nabu/Nisaba profiles, Hindsight, vault tools and timers; refresh README for the 27B setup - 2026-10-08
10149cddev agent: revise_task, phone-code release gate, discard safeguards - 2026-10-08
86b5201Trim Hermes toolsets and prompt; check lints changed files; Claude models per job - 2026-10-08
c6cd714dev agent: release_prod and confirm_release with a phone-code gate - 2026-10-08
8039cf5Ollama: cap llama-server prompt cache at 1 GiB, keep-alive 30m - 2026-10-08
b0c71c9deploy_dev creates Payload migrations automatically - 2026-10-08
0e29c48release_notes saves the release command on the dev VM, notes without caveats - 2026-10-08
92093e7MCP servers: stdin from /dev/null, release_notes with inline diff - 2026-10-08
6bd1d03dev agent: release_notes gets diff inline, start_task guard - 2026-10-08
f97adf4Hermes dev agent: profile, SOUL and dev-tools MCP server for keateswebsite - 2026-10-07
13d8969MCP home tools, headless page checker with auto-fix loop, website pages - 2026-10-07
45daff0Weather briefing hook, website server, whisper STT, qwen3.8 27B modelfile, Ollama 0.40 override - 2026-09-20
f52d94dAdd random-fact script and say-watch units; SOUL.md speech rules - 2026-09-20
bdb8743Initial capture of Ollama/Hermes/HA setup