Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
009a474e90 | ||
|
|
dc2225d384 | ||
|
|
3cd843072d | ||
|
|
98c4a2a02b | ||
|
|
d794c98505 |
@@ -0,0 +1,61 @@
|
||||
# Ornith-1.0-9B vs gpt-oss-20b — P100 benchmark (2026-06-27)
|
||||
|
||||
**TL;DR:** Ornith-1.0-9B works cleanly as a Hermes backend (tool-calls, `<think>`,
|
||||
content all correct) and matches gpt-oss-20b on **code quality** — but it is a **dense
|
||||
9B**, so on the compute-bound P100 it generates **~2–3× slower** than the MoE gpt-oss-20b
|
||||
(~6.3 vs ~13–23 tok/s). **Keep gpt-oss-20b as the default daily driver.** Ornith earns a
|
||||
spot in the menu as a coding *specialist* to A/B on real tasks, but doesn't displace it.
|
||||
|
||||
## What was done
|
||||
- Downloaded `ornith-1.0-9b-Q5_K_M.gguf` (6.47 GB, exact byte match) → `/storage1/labdata/llm/models/`.
|
||||
- Added `ornith-1.0-9b` to `stacks/llm/llama-swap-config.yaml` (same Pascal macro: q8/q8 KV,
|
||||
`--parallel 1`, `--flash-attn on`, `--jinja`, 64k ctx; native 256k so no YaRN). Deployed to
|
||||
`/config/llm/` + restarted llama-swap. **Live in the menu now.**
|
||||
- Quant choice: **Q5_K_M** (safe overnight, no OOM). Loads using only **7.7 GB VRAM** at 64k —
|
||||
huge headroom, so Q6_K or Q8_0 (9.5 GB, near-lossless) would also fit easily if you want more quality.
|
||||
|
||||
## Results (identical prompts, temp 0.6 / top_p 0.95 / top_k 20)
|
||||
|
||||
| Test | Metric | **ornith-1.0-9b** | **gpt-oss-20b** | Winner |
|
||||
|---|---|---|---|---|
|
||||
| Tool call | emits valid `tool_calls`? | ✅ `get_weather({"city":"Tokyo"})` | ✅ identical | tie |
|
||||
| Codegen (merge_intervals) | correct? | ✅ correct, non-mutating, tests pass | ✅ correct (mutates input list) | ornith (slightly cleaner) |
|
||||
| Debug (second_largest) | correct? | ✅ correct + edge-case guard | ✅ correct + O(n) alt | tie (gpt-oss more thorough) |
|
||||
| **Gen speed** | tok/s (codegen) | **6.4** | **21.7** | **gpt-oss 3.4×** |
|
||||
| **Gen speed** | tok/s (debug) | **6.4** | **18.9** | **gpt-oss 2.9×** |
|
||||
| Prefill (small) | tok/s | 49–104 | 133–188 | gpt-oss |
|
||||
| Prefill (deep ~25–30k ctx) | tok/s | 101.9 (n=30295) | 154.9 (n=23422) | gpt-oss 1.5× |
|
||||
| Reasoning verbosity | think chars (codegen/debug) | 433 / 452 (concise) | 1671 / 2118 (verbose) | — |
|
||||
| VRAM @ 64k | MiB | **7684** | ~12600 | ornith (more headroom) |
|
||||
|
||||
## Why the speed gap (the important takeaway)
|
||||
gpt-oss-20b is **MoE with ~3.6B active params/token**; Ornith-9B is **dense (9B active/token)**.
|
||||
The P100 (GP100, cc 6.0) is compute-bound, so per-token cost scales with *active* params —
|
||||
2.5× more active params ≈ the ~2.5–3× slower generation we measured. This is architectural,
|
||||
not a config problem; no amount of tuning closes it. Your memory's "~5 tok/s ceiling" held for
|
||||
the MoE models; a dense 9B genuinely sits below that line on this GPU.
|
||||
|
||||
## Verdict for your Hermes backend
|
||||
- **Default stays gpt-oss-20b.** Gen speed is already the UX pain point (~6 vs ~20 tok/s is the
|
||||
difference between usable and painful for interactive agent loops), and Ornith doesn't win on
|
||||
quality to justify being 3× slower.
|
||||
- **Keep Ornith as a menu specialist.** It's MIT, purpose-built for agentic coding, refreshingly
|
||||
concise (less token waste on overthinking), and tool-calls cleanly. Good for one-shot coding
|
||||
asks where you'll wait for quality.
|
||||
- **The real coding upgrade you already have on disk:** `Qwen3-Coder-30B-A3B-Instruct-UD-Q2_K_XL.gguf`
|
||||
is a **coder-tuned MoE (3B active)** — it would be both *faster* than Ornith (MoE) *and*
|
||||
code-specialized. If you want a faster coding model than gpt-oss, that's the one to benchmark
|
||||
next, not Ornith.
|
||||
|
||||
## Caveats
|
||||
- Benchmarks are a small hand-written suite (4 tasks), not SWE-bench. Ornith's headline 69.4
|
||||
SWE-Bench Verified is **self-reported/unverified** by DeepReinforce.
|
||||
- The `deep_prefill` row measures prefill speed only — both models hit the 256-token cap mid-think
|
||||
(`finish=length`, empty `content`), which is expected for that probe.
|
||||
- Raw responses saved on valhalla at `/tmp/ornith-bench/` (one `.json` per model+test).
|
||||
|
||||
## Open decision for you
|
||||
The repo config change (`stacks/llm/llama-swap-config.yaml`) is **deployed to the host but NOT
|
||||
committed/pushed** — I don't push without your say-so, and pushing would trigger a Portainer
|
||||
redeploy of stack 34. Tell me to commit+push if you want the repo (canonical source) to match the
|
||||
live host, or to revert the menu entry if you'd rather not keep Ornith around.
|
||||
@@ -0,0 +1,780 @@
|
||||
# Hermes Ecosystem Integration Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Integrate selected Hermes-ecosystem tools into ginnoir's live valhalla deployment — a host-side delegation skill and self-improvement plugin (Phase 1), a stealth-browser homelab stack and a skill pre-filter trial (Phase 2), and an optional UI upgrade (Phase 3) — each reversible and sized for the single-P100 / weak-local-model constraints.
|
||||
|
||||
**Architecture:** Two integration classes. **Class A** (host-side Hermes plugins/skills) install into `~/.hermes/` on the valhalla host and are applied by SSH + `hermes` CLI + `sudo systemctl restart hermes-gateway.service`; they are **host-managed, NOT committed to this repo** (tracked in project memory + the Obsidian vault, like the rustdesk/obsidian/xvfb units). **Class B** (Docker services) become `stacks/<name>/` entries deployed via the normal Gitea-poll path, fronted by Caddy `internal_only` + Authentik. The companion spec is `docs/superpowers/specs/2026-06-27-hermes-ecosystem-integration-design.md`.
|
||||
|
||||
**Tech Stack:** Hermes Agent v0.17.0 (host systemd), llama-swap/Tesla P100 backend (`gpt-oss-20b`, `--parallel 1`), Python 3.11 (`~/.hermes/hermes-agent/venv`), `uv`, SQLite, Docker Compose + Portainer (Gitea-polled), Caddy, Authentik, Codex + Claude Code CLIs.
|
||||
|
||||
---
|
||||
|
||||
## How to read this plan (operational, not codebase-TDD)
|
||||
|
||||
These are operational integrations against a live host and third-party services, so the TDD rhythm
|
||||
is adapted: each task is **back up → change → verify with a smoke test → document/commit**. The
|
||||
"test" is a real verification command with expected output. **Class A (host) changes are not git
|
||||
commits** — their checkpoint is a backup + smoke test + a memory/vault note. **Class B (repo)
|
||||
changes do commit** (and push triggers Portainer). Run every step from the Windows workstation;
|
||||
host steps use `ssh -o BatchMode=yes ginnoir@valhalla "..."`.
|
||||
|
||||
**Global guardrails (apply to every task):**
|
||||
- `hermes` is only on the **login-shell** PATH → over SSH call it by full path: `~/.local/bin/hermes`.
|
||||
- Gateway restart needs root: `sudo systemctl restart hermes-gateway.service`.
|
||||
- Always back up `~/.hermes/config.yaml` before editing (`cp ...bak.$(date +%s)`).
|
||||
- **Never** load a second model onto the P100. Keep curator/eagle-eye semantic layers on CPU or off.
|
||||
- Read third-party code before running it (curator writes skills; acp-skill spawns external agents; camofox automates a browser).
|
||||
|
||||
**Decisions (RESOLVED 2026-06-27 — all phases actionable):** trial **both** UIs and keep the winner
|
||||
(Phase 3); curator stays **report-only** (Task 3); **trial eagle-eye** — it's the only direct
|
||||
skill-router in the ecosystem (Task 6); camofox wired as a **minimal 2-tool skill** (Task 5 Step 8).
|
||||
|
||||
---
|
||||
|
||||
# PHASE 1 — Host-side, reversible, high-leverage (actionable now)
|
||||
|
||||
## Task 1: Pre-flight — capture current Hermes state
|
||||
|
||||
**Files:**
|
||||
- Host only (no repo files).
|
||||
|
||||
- [ ] **Step 1: Verify host reachability and Hermes services are up**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "systemctl is-active hermes-gateway.service hermes-dashboard.service hermes-webui.service"
|
||||
```
|
||||
Expected: three lines, each `active`.
|
||||
|
||||
- [ ] **Step 2: Snapshot config + inventory skills/plugins/sessions dirs**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "cp ~/.hermes/config.yaml ~/.hermes/config.yaml.bak.preflight.$(date +%s) && ls -la ~/.hermes/skills ~/.hermes/plugins ~/.hermes/sessions 2>&1 | head -60 && ~/.local/bin/hermes --version"
|
||||
```
|
||||
Expected: a backup is created; directory listings print (note whether `~/.hermes/plugins` exists yet); `hermes` prints a version (≈ v0.17.0). Record the skills-dir path — confirms `~/.hermes/skills` is correct for later tasks.
|
||||
|
||||
- [x] **Step 3: Confirm Codex and Claude Code are invocable — DONE 2026-06-27 (installed this session)**
|
||||
|
||||
Both delegation CLIs were installed on valhalla this session:
|
||||
- `claude` → `~/.local/bin/claude` **v2.1.195** (login pending)
|
||||
- `codex` → `/usr/bin/codex` **v0.142.3** (login pending; harmless PATH-alias warning at install)
|
||||
|
||||
**Gotcha recorded:** `/home/ginnoir/.claude` existed as an empty **root-owned** dir (created Jun 17,
|
||||
likely a prior sudo op) and blocked the installer until `sudo chown ginnoir:ginnoir ~/.claude`. Codex
|
||||
global install needs `sudo` (npm global prefix is `/usr`). Re-verify any time with:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "bash -lc 'claude --version; codex --version'"
|
||||
```
|
||||
**ginnoir must log in** to each (`claude`, then `codex login`) before Task 2's external delegation
|
||||
smoke-tests will succeed. Cursor + Antigravity targets are added later in **Task 10**.
|
||||
|
||||
- [ ] **Step 4: Checkpoint**
|
||||
|
||||
No commit (host inventory only). Record findings (skills-dir path, whether `plugins/` exists, Codex/Claude availability) in the session notes for use in Tasks 2–3.
|
||||
|
||||
---
|
||||
|
||||
## Task 2: Install `hermes-agent-acp-skill` (multi-agent delegation)
|
||||
|
||||
**Files:**
|
||||
- Host: `~/.hermes/skills/hermes-acp-orchestrator/` (skill files), `~/.hermes/config.yaml` (delegation block).
|
||||
- Scratch: clone under `/storage1/hermes/workspace/clones/` (never root; see the disk gotcha).
|
||||
|
||||
- [ ] **Step 1: Clone and read the skill before installing**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "mkdir -p /storage1/hermes/workspace/clones && git -C /storage1/hermes/workspace/clones clone https://github.com/Rainhoole/hermes-agent-acp-skill && sed -n '1,200p' /storage1/hermes/workspace/clones/hermes-agent-acp-skill/SKILL.md"
|
||||
```
|
||||
Expected: repo clones; `SKILL.md` prints. **Read it** to confirm: the skill folder/name, how `delegate_task()` is wired, and whether it expects a specific install path or a config key. The README omits install steps, so the SKILL.md is authoritative — follow whatever placement it documents. If SKILL.md specifies a different mechanism than the manual copy below, use SKILL.md's.
|
||||
|
||||
- [ ] **Step 2: Place the skill into the Hermes skills directory**
|
||||
|
||||
Run (adjust the destination name to match SKILL.md's declared skill name):
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "mkdir -p ~/.hermes/skills/hermes-acp-orchestrator && cp -r /storage1/hermes/workspace/clones/hermes-agent-acp-skill/SKILL.md /storage1/hermes/workspace/clones/hermes-agent-acp-skill/README.md ~/.hermes/skills/hermes-acp-orchestrator/ && ls -la ~/.hermes/skills/hermes-acp-orchestrator/"
|
||||
```
|
||||
Expected: `SKILL.md` and `README.md` present in the new skill dir.
|
||||
|
||||
- [ ] **Step 3: Add the delegation config block (with a safe backup)**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "cp ~/.hermes/config.yaml ~/.hermes/config.yaml.bak.acp.$(date +%s) && printf '\ndelegation:\n external_timeout_seconds: 900\n external_max_output_chars: 24000\n' >> ~/.hermes/config.yaml && tail -8 ~/.hermes/config.yaml"
|
||||
```
|
||||
Expected: a `.bak.acp.*` backup exists; the `delegation:` block is appended and printed. (If SKILL.md says the block belongs under a different key or nesting, edit accordingly instead of this append.)
|
||||
|
||||
- [ ] **Step 4: Restart the gateway and confirm the skill registers**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "sudo systemctl restart hermes-gateway.service && sleep 5 && systemctl is-active hermes-gateway.service && ~/.local/bin/hermes skills list 2>&1 | grep -i acp"
|
||||
```
|
||||
Expected: gateway `active`; the ACP/orchestrator skill appears in `hermes skills list`. (If the subcommand differs, use `~/.local/bin/hermes skills --help` to find the list command — verify on host.)
|
||||
|
||||
- [ ] **Step 5: Smoke-test a trivial delegation to the local hermes subagent first**
|
||||
|
||||
Run (a no-external-dependency delegation — routes to `hermes`, not Codex/Claude, to isolate the skill from CLI availability):
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "~/.local/bin/hermes run 'Use delegate_task to ask a hermes subagent to reply with exactly the word PONG, then report its output.' 2>&1 | tail -30"
|
||||
```
|
||||
Expected: the delegated subagent returns `PONG` and the parent reports it. **This proves the skill mechanics.** (Exact `hermes` one-shot invocation may differ — confirm the non-interactive run command via `~/.local/bin/hermes --help` in Step 1's read-through.)
|
||||
|
||||
- [ ] **Step 6: Smoke-test an external delegation (only if Codex/Claude were found in Task 1)**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "~/.local/bin/hermes run 'Use delegate_task with agent=claude-code to print the current working directory and nothing else, then report it.' 2>&1 | tail -40"
|
||||
```
|
||||
Expected: Claude Code is spawned within the 900 s timeout, returns the cwd, output is captured under the 24,000-char cap. **If it hangs or auths interactively**, the external CLI needs non-interactive credentials on the service env — note for ginnoir; the `hermes`-target path (Step 5) still works.
|
||||
|
||||
- [ ] **Step 7: Checkpoint (host note + reversibility recorded)**
|
||||
|
||||
No git commit. Record in session notes: skill installed at `~/.hermes/skills/hermes-acp-orchestrator/`, config backup at `~/.hermes/config.yaml.bak.acp.*`. **Rollback** = `rm -rf ~/.hermes/skills/hermes-acp-orchestrator`, restore the `.bak.acp.*`, restart gateway.
|
||||
|
||||
---
|
||||
|
||||
## Task 3: Install `hermes-curator-evolver` (self-improvement, report-only)
|
||||
|
||||
**Files:**
|
||||
- Host: `~/.hermes/plugins/curator-evolver/` (plugin + `data/evidence.sqlite`), systemd **user** timer.
|
||||
|
||||
- [ ] **Step 1: Read the plugin source before installing (it can write to skills)**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "git -C /storage1/hermes/workspace/clones clone https://github.com/pingchesu/hermes-curator-evolver && sed -n '1,160p' /storage1/hermes/workspace/clones/hermes-curator-evolver/README.md"
|
||||
```
|
||||
Expected: repo clones; README prints. Confirm the apply path requires `--approve` (it does per the README) and that `auto-run` without `--apply-low-risk --approve-auto-apply` is **dry-run only**.
|
||||
|
||||
- [ ] **Step 2: Install the plugin (no semantic/embedding extras — keep it off the P100)**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "bash -lc '~/.local/bin/hermes plugins install pingchesu/hermes-curator-evolver --enable && uv pip install --python ~/.hermes/hermes-agent/venv/bin/python -e ~/.hermes/plugins/curator-evolver && ~/.hermes/hermes-agent/venv/bin/hermes-curator-evolver bootstrap'"
|
||||
```
|
||||
Expected: plugin installs to `~/.hermes/plugins/curator-evolver`; editable pip install succeeds; `bootstrap` configures and installs a **systemd user timer**. **Do NOT pass `--semantic`** (that pulls Qwen/BGE models — CPU/VRAM cost we're avoiding for now; BM25/FTS ranking is the v1 default).
|
||||
|
||||
- [ ] **Step 3: Backfill recent sessions and generate the first dry-run report**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "~/.hermes/hermes-agent/venv/bin/hermes-curator-evolver backfill-sessions --sessions-dir ~/.hermes/sessions --days 30 --format json 2>&1 | tail -20 && ~/.hermes/hermes-agent/venv/bin/hermes-curator-evolver report --days 7 --format json 2>&1 | tail -40"
|
||||
```
|
||||
Expected: evidence is mined into `~/.hermes/plugins/curator-evolver/data/evidence.sqlite`; `report` prints a JSON summary of candidate skill improvements. **No skill files are modified** (report is read-only).
|
||||
|
||||
- [ ] **Step 4: Generate a dry-run proposal for one skill and inspect it**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "~/.hermes/hermes-agent/venv/bin/hermes-curator-evolver auto-run --skills-dir ~/.hermes/skills --format json 2>&1 | tail -60"
|
||||
```
|
||||
Expected: a JSON set of **proposed** (not applied) edits. Confirm no files under `~/.hermes/skills` changed:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "find ~/.hermes/skills -newermt '-10 minutes' -type f 2>/dev/null"
|
||||
```
|
||||
Expected: empty output (nothing modified) — proves dry-run safety.
|
||||
|
||||
- [ ] **Step 5: Confirm the scheduled timer is report-only**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "bash -lc 'systemctl --user list-timers \"hermes-curator-evolver*\" --all --no-pager' && ssh -o BatchMode=yes ginnoir@valhalla \"systemctl --user cat 'hermes-curator-evolver*' 2>&1 | grep -iE 'ExecStart|approve|apply'\""
|
||||
```
|
||||
Expected: a timer is listed; its `ExecStart` runs `auto-run` **without** `--apply-low-risk`/`--approve-auto-apply`. **If the bootstrap-installed unit includes those flags, override it** to remove them (the morning decision in spec §6.2 defaults to report-only). If user-lingering isn't enabled the timer won't fire across logout — enable with `sudo loginctl enable-linger ginnoir` (note for ginnoir).
|
||||
|
||||
- [ ] **Step 6: Checkpoint (host note + reversibility recorded)**
|
||||
|
||||
No git commit. Record: plugin at `~/.hermes/plugins/curator-evolver`, DB at `.../data/evidence.sqlite`, timer name, report-only confirmed. **Rollback** = `systemctl --user disable --now <timer>`, `~/.local/bin/hermes plugins uninstall curator-evolver` (verify exact uninstall verb), `rm -rf ~/.hermes/plugins/curator-evolver`.
|
||||
|
||||
---
|
||||
|
||||
## Task 3b: Install `hermes-motif` (skill DISCOVERY, proposal-only)
|
||||
|
||||
> Complements curator-evolver — does **not** compete with it (spec §7.1). motif *discovers new*
|
||||
> skills by mining repeated tool sequences; curator *refines existing* ones. **Zero P100 cost**
|
||||
> (makes no LLM calls). Together with eagle-eye (routing) they form a skill factory:
|
||||
> motif creates → curator refines → eagle-eye routes.
|
||||
|
||||
**Files:**
|
||||
- Host: `~/.hermes/plugins/` (motif plugin), `~/.hermes/plugins/<motif>/plugin/plugin.yaml`.
|
||||
|
||||
- [ ] **Step 1: Clone and read; confirm proposal-only config**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "git -C /storage1/hermes/workspace/clones clone https://github.com/Saurav0989/hermes-motif && sed -n '1,160p' /storage1/hermes/workspace/clones/hermes-motif/README.md && cat /storage1/hermes/workspace/clones/hermes-motif/plugin/plugin.yaml 2>&1"
|
||||
```
|
||||
Expected: README + `plugin.yaml` print. **Confirm `auto_install: false`** (proposal-only) and note
|
||||
`min_occurrences` / sequence-length thresholds. Note the referenced Hermes trace bug (#12922) that
|
||||
can affect trace completeness — acceptable for a proposal-only trial.
|
||||
|
||||
- [ ] **Step 2: Install the plugin**
|
||||
|
||||
Run (per its README — clone + pip + `scripts/install_plugin.sh`):
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "cd /storage1/hermes/workspace/clones/hermes-motif && bash scripts/install_plugin.sh 2>&1 | tail -20"
|
||||
```
|
||||
Expected: the plugin lands under `~/.hermes/plugins/` and registers. (If the script expects a
|
||||
different layout, follow the README's exact steps.)
|
||||
|
||||
- [ ] **Step 3: Verify it mines and PROPOSES without modifying skills**
|
||||
|
||||
Restart the gateway, run the agent through a couple of repeated multi-tool workflows, then check for
|
||||
proposals (drafts), confirming nothing under `~/.hermes/skills` was auto-written:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "sudo systemctl restart hermes-gateway.service && sleep 5 && find ~/.hermes/plugins -iname '*propos*' -o -iname '*draft*' 2>/dev/null | head && find ~/.hermes/skills -newermt '-10 minutes' -type f 2>/dev/null"
|
||||
```
|
||||
Expected: proposal/draft artifacts may appear under the plugin dir; the second `find` is **empty**
|
||||
(no skill files auto-modified) — proves `auto_install: false` safety.
|
||||
|
||||
- [ ] **Step 4: Checkpoint**
|
||||
|
||||
No repo commit (host-side). **Rollback** = remove the motif plugin dir + restart gateway. Record in
|
||||
`memory/hermes-extensions.md` alongside curator (skill factory: motif=create, curator=refine).
|
||||
|
||||
---
|
||||
|
||||
## Task 4: Document Phase 1 in memory + vault (durable knowledge)
|
||||
|
||||
**Files:**
|
||||
- Memory: `C:\Users\MattC\.claude\projects\C--Users-MattC-Documents-homelabstack\memory\hermes-extensions.md` + `MEMORY.md` pointer.
|
||||
- Vault: append to the Hermes project note via Obsidian MCP (`mcp__obsidian__*`).
|
||||
|
||||
- [ ] **Step 1: Write the memory file**
|
||||
|
||||
Create `memory/hermes-extensions.md` (frontmatter `type: project`) recording: acp-skill installed (delegation to hermes/codex/claude-code/cursor/antigravity, 900s/24k caps); curator-evolver installed **report-only** (CPU ranking, no `--semantic`, no auto-apply flags); **motif** installed proposal-only (skill factory: motif creates → curator refines → eagle-eye routes); **claude v2.1.195 + codex v0.142.3 installed on valhalla 2026-06-27** (login pending; `~/.claude` was root-owned → chowned); exact paths and rollback commands; the host-vs-repo boundary. Link `[[llm-stack-hermes]]`, `[[multi-agent-tool-configs]]`, `[[obsidian-app-on-valhalla]]`.
|
||||
|
||||
- [ ] **Step 2: Add the MEMORY.md index pointer**
|
||||
|
||||
Append one line to `MEMORY.md`:
|
||||
`- [Hermes host extensions](hermes-extensions.md) — acp delegation skill + curator-evolver (report-only) on valhalla; host-managed in ~/.hermes, not in the repo`
|
||||
|
||||
- [ ] **Step 3: Write back to the Obsidian vault**
|
||||
|
||||
Per the global rule, use the Obsidian MCP (never write CouchDB directly) to append a session note to the Hermes project folder summarizing Phase 1 (what, why report-only, rollback). If the MCP is unreachable, tell ginnoir and skip — do not hand-edit.
|
||||
|
||||
- [ ] **Step 4: Checkpoint**
|
||||
|
||||
No code commit required (memory files live outside the repo). Phase 1 complete and documented.
|
||||
|
||||
---
|
||||
|
||||
# PHASE 2 — New capability + experiment
|
||||
|
||||
> Decisions resolved (spec §6.3 eagle-eye trial; §6.4 camofox minimal). Actionable.
|
||||
|
||||
## Task 5: `camofox-browser` as a homelab stack (Class B)
|
||||
|
||||
**Files:**
|
||||
- Create: `stacks/camofox/docker-compose.yml`, `stacks/camofox/stack.env`.
|
||||
- Modify: `Caddyfile` (new site block), `bookmarks-domains.html` + `bookmarks-ports.html` (regenerated).
|
||||
- Host (image): build under `/storage1/hermes/workspace/clones/camofox-browser`.
|
||||
|
||||
- [ ] **Step 1: Decide image provenance and build it**
|
||||
|
||||
camofox publishes **no registry image** (`make up` builds locally). Recommended default: build on
|
||||
valhalla and tag `camofox-browser:local`, reference that tag from compose (Watchtower already
|
||||
disabled for pinned infra). Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "git -C /storage1/hermes/workspace/clones clone https://github.com/jo-inc/camofox-browser && cd /storage1/hermes/workspace/clones/camofox-browser && docker build -t camofox-browser:local . 2>&1 | tail -20 && docker image ls camofox-browser:local"
|
||||
```
|
||||
Expected: image builds; `camofox-browser:local` is listed. **Alternative (if a reproducible/Gitea-Actions build is preferred, like famapp):** build + push to `registry.ginnoir.com/ginnoir/camofox-browser` and reference that instead — flag this choice for ginnoir.
|
||||
|
||||
- [ ] **Step 2: Write the stack compose**
|
||||
|
||||
Create `stacks/camofox/docker-compose.yml`:
|
||||
```yaml
|
||||
# camofox stack — stealth headless browser REST API for the Hermes agent.
|
||||
# No published image: built on-host as camofox-browser:local (see plan Task 5).
|
||||
# Internal-only; reachable by Caddy over edge and by host-side Hermes.
|
||||
services:
|
||||
camofox:
|
||||
image: camofox-browser:local
|
||||
container_name: camofox
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "com.centurylabs.watchtower.enable=false"
|
||||
env_file:
|
||||
- stack.env
|
||||
networks: [edge, camofox]
|
||||
volumes:
|
||||
- /config/camofox/cookies:/home/node/.camofox/cookies
|
||||
- /config/camofox/profiles:/home/node/.camofox/profiles
|
||||
ports:
|
||||
- "172.20.0.1:9377:9377"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsS", "http://localhost:9377/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
start_period: 40s
|
||||
|
||||
networks:
|
||||
edge:
|
||||
external: true
|
||||
camofox:
|
||||
name: camofox
|
||||
driver: bridge
|
||||
```
|
||||
(The `172.20.0.1:9377` host-port mirrors the llm stack's pattern so host-side Hermes can reach it directly; Caddy reaches it over `edge` by container name.)
|
||||
|
||||
- [ ] **Step 3: Write `stack.env` (secrets; LF endings)**
|
||||
|
||||
Create `stacks/camofox/stack.env` with a generated bearer key (replace the value with a real secret before push):
|
||||
```
|
||||
CAMOFOX_ACCESS_KEY=GENERATE_A_LONG_RANDOM_KEY
|
||||
CAMOFOX_ADMIN_KEY=GENERATE_A_SECOND_RANDOM_KEY
|
||||
CAMOFOX_PORT=9377
|
||||
```
|
||||
Generate the keys: `ssh ... "openssl rand -hex 32"` (run twice). **Ensure LF line endings** (`.gitattributes` enforces this — verify the file isn't CRLF before committing). Leave `CAMOFOX_API_KEY` unset (cookie-import endpoint stays disabled).
|
||||
|
||||
- [ ] **Step 4: Add the Caddy site block (internal-only)**
|
||||
|
||||
Add to `Caddyfile` (place near other internal admin services). Since camofox enforces its own bearer auth and Hermes calls it machine-to-machine, gate by LAN only (no Authentik forward-auth, which would block the agent's API calls):
|
||||
```caddy
|
||||
camofox.ginnoir.com {
|
||||
import internal_only
|
||||
reverse_proxy camofox:9377
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Create host config dirs, regenerate bookmarks, then deploy**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "sudo mkdir -p /config/camofox/cookies /config/camofox/profiles && sudo chown -R ginnoir:ginnoir /config/camofox"
|
||||
```
|
||||
Then regenerate bookmarks and push (Portainer must have the `stacks/camofox` git stack registered — see Step 6):
|
||||
```powershell
|
||||
./scripts/gen-bookmarks.ps1
|
||||
git add stacks/camofox/ Caddyfile bookmarks-domains.html bookmarks-ports.html
|
||||
git commit -m "feat(camofox): stealth browser stack for the Hermes agent"
|
||||
git push
|
||||
```
|
||||
Expected: commit + push; Gitea Actions reloads Caddy (Caddyfile changed); Portainer redeploys the camofox stack within 5 min.
|
||||
|
||||
- [ ] **Step 6: Register the stack in Portainer if new, and verify it runs**
|
||||
|
||||
New stacks need one-time Portainer registration (see `portainer-new-stack-registration` memory). After deploy, verify:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "docker ps --filter name=camofox --format '{{.Names}} {{.Status}}' && curl -fsS http://172.20.0.1:9377/health"
|
||||
```
|
||||
Expected: container `Up (healthy)`; `/health` returns OK.
|
||||
|
||||
- [ ] **Step 7: Smoke-test the browser API end-to-end**
|
||||
|
||||
Run (creates a tab, snapshots a page):
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "K=\$(grep CAMOFOX_ACCESS_KEY /config/portainer/compose/*/stacks/camofox/stack.env | cut -d= -f2); ID=\$(curl -fsS -H \"Authorization: Bearer \$K\" -H 'Content-Type: application/json' -d '{\"userId\":\"smoke\",\"sessionKey\":\"t1\",\"url\":\"https://example.com\"}' http://172.20.0.1:9377/tabs | python3 -c 'import sys,json;print(json.load(sys.stdin)[\"id\"])'); curl -fsS -H \"Authorization: Bearer \$K\" \"http://172.20.0.1:9377/tabs/\$ID/snapshot?userId=smoke\" | head -20"
|
||||
```
|
||||
Expected: a tab id comes back; the snapshot returns accessibility text containing "Example Domain". (Adjust the JSON id field name to match the real response from Step 1's README read.)
|
||||
|
||||
- [ ] **Step 8: Wire camofox into Hermes as a minimal tool surface (per §6.4 decision)**
|
||||
|
||||
Default recommendation: a **small Hermes skill** (2 high-level tools — `browse(url)` and `search(query)`) that curls camofox, rather than exposing the full REST surface (respects the tool-budget that keeps gpt-oss-20b functional). Create `~/.hermes/skills/camofox-browse/SKILL.md` documenting the two operations against `http://172.20.0.1:9377` with the bearer key, restart the gateway, and smoke-test:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "sudo systemctl restart hermes-gateway.service && sleep 5 && ~/.local/bin/hermes run 'browse https://example.com and tell me the page heading' 2>&1 | tail -20"
|
||||
```
|
||||
Expected: Hermes uses the camofox tool and reports "Example Domain". **If §6.4 chose an MCP shim instead**, build/register the MCP server and add it to `mcp_servers:` with a 2-tool `tools.include` allowlist (per the MCP-curation pattern in `llm-stack-hermes`).
|
||||
|
||||
- [ ] **Step 9: Checkpoint**
|
||||
|
||||
Repo changes are committed (Step 5). Update `memory/hermes-extensions.md` + the vault note with the camofox stack + tool wiring and the bearer-key location.
|
||||
|
||||
---
|
||||
|
||||
## Task 5b: Install `hermes-web-search-plus` (multi-provider search; pairs with camofox)
|
||||
|
||||
> Mature (v2.6.1, MIT, stdlib-only). Complements camofox (spec §7.2): search-plus *finds* via cheap
|
||||
> provider APIs, camofox *browses/renders*. Lighter and higher-frequency — good default reach-for.
|
||||
|
||||
**Files:**
|
||||
- Host: `~/.hermes/plugins/` (plugin), provider key(s) in `~/.hermes/config.yaml` (or the plugin's config).
|
||||
|
||||
- [ ] **Step 1: Install the plugin**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "bash -lc '~/.local/bin/hermes plugins install robbyczgw-cla/hermes-web-search-plus --enable'"
|
||||
```
|
||||
Expected: plugin installs and enables.
|
||||
|
||||
- [ ] **Step 2: Configure at least one provider key (free tier)**
|
||||
|
||||
All provider keys are optional but ≥1 is needed to function. Pick a free-tier provider (e.g. Tavily,
|
||||
Exa, or self-hosted SearXNG; Keenable has a keyless public tier). Add the key per the plugin's README
|
||||
(read `/storage1/hermes/workspace/clones/...` or the plugin docs for the exact env/config key), then:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "sudo systemctl restart hermes-gateway.service && sleep 5 && systemctl is-active hermes-gateway.service"
|
||||
```
|
||||
Expected: gateway `active`. **Mind the tool-budget rule** — if it exposes both `web_search_plus` +
|
||||
extract, that's fine (2 tools); don't also enable redundant search MCPs.
|
||||
|
||||
- [ ] **Step 3: Smoke-test a search**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "~/.local/bin/hermes run 'search the web for the latest Hermes Agent release version and cite the source' 2>&1 | tail -20"
|
||||
```
|
||||
Expected: the agent calls the search tool, returns a current result with a source URL.
|
||||
|
||||
- [ ] **Step 4: Checkpoint**
|
||||
|
||||
No repo commit (host-side). Document the chosen provider + key location in `memory/hermes-extensions.md`.
|
||||
|
||||
---
|
||||
|
||||
## Task 6: Trial `eagle-eye` skill pre-filter (Class A, behind a switch)
|
||||
|
||||
> Confirmed the chosen tool: eagle-eye is the **only** direct skill-router in the Hermes ecosystem
|
||||
> (per `awesome-hermes-agent` / Hermes Atlas). It directly serves the goal of "many skills installed,
|
||||
> few injected per turn." Complementary (not a substitute) and worth a later look on the *tool* side:
|
||||
> `llmtrim` (compresses tool schemas + MCP output before each request). `hermes-motif` overlaps
|
||||
> curator-evolver (trace→micro-skill), not this router.
|
||||
|
||||
**Files:**
|
||||
- Host: `~/.hermes/plugins/eagle-eye/` (or skills dir per its README), config toggle in `~/.hermes/config.yaml`.
|
||||
|
||||
- [ ] **Step 1: Clone and read; confirm graceful-degradation and the jieba dependency**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "git -C /storage1/hermes/workspace/clones clone https://github.com/willingning-coder/eagle-eye && sed -n '1,200p' /storage1/hermes/workspace/clones/eagle-eye/README.md"
|
||||
```
|
||||
Expected: README prints. Confirm the install hook, the on/off switch, and that L2–L5 (incl. dense embeddings) are optional. **Plan to run with the dense layer disabled** (CPU/keep off the P100) — lean on L1 (hard triggers) + L2 (BM25) only for the trial.
|
||||
|
||||
- [ ] **Step 2: Install with an easy off-switch and minimal deps**
|
||||
|
||||
Install per the README (likely `~/.local/bin/hermes plugins install willingning-coder/eagle-eye --enable`), then restart the gateway:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "bash -lc '~/.local/bin/hermes plugins install willingning-coder/eagle-eye --enable' && ssh -o BatchMode=yes ginnoir@valhalla 'sudo systemctl restart hermes-gateway.service && systemctl is-active hermes-gateway.service'"
|
||||
```
|
||||
Expected: plugin enabled; gateway `active`. (If install fails on `jieba`, `uv pip install --python ~/.hermes/hermes-agent/venv/bin/python jieba` then retry — note the foreign-language dep for maintenance.)
|
||||
|
||||
- [ ] **Step 3: A/B test skill selection on representative prompts**
|
||||
|
||||
Pick 5 prompts that should each map to a known skill and 2 that should map to none. Run each with eagle-eye enabled, then disable it (`~/.local/bin/hermes plugins disable eagle-eye` + gateway restart) and run the same 7. Record which skills each surfaced and whether the local model then picked the right one.
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "~/.local/bin/hermes run '<representative prompt>' 2>&1 | tail -25"
|
||||
```
|
||||
Expected: with eagle-eye on, the prompt's prompt-injected skill candidates are ≤5 and include the right one; the "no skill needed" prompts proceed without forced skill loading.
|
||||
|
||||
- [ ] **Step 4: Keep-or-cut decision**
|
||||
|
||||
**Keep only if** skill selection measurably improved (right skill surfaced more often AND/OR fewer wrong skills loaded) without regressions. Otherwise disable and uninstall:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "~/.local/bin/hermes plugins uninstall eagle-eye && sudo systemctl restart hermes-gateway.service"
|
||||
```
|
||||
Record the verdict + evidence in `memory/hermes-extensions.md`.
|
||||
|
||||
- [ ] **Step 5: Checkpoint**
|
||||
|
||||
No repo commit (host-side). Document the A/B result and final state (kept/cut) in memory + vault.
|
||||
|
||||
---
|
||||
|
||||
# PHASE 2b — Delegation fabric & context efficiency
|
||||
|
||||
> Extends acp-skill (Task 2) from 3 targets to 4 external agents, and adds optional token-trimming.
|
||||
|
||||
## Task 10: Wire Cursor + Antigravity into the delegation fabric
|
||||
|
||||
**Files:**
|
||||
- Host: Cursor + `agy` binaries; acp-skill config or a generic shell-agent skill in `~/.hermes/skills/`.
|
||||
|
||||
- [ ] **Step 1: Install the Cursor CLI (official cursor.com)**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "bash -lc 'curl https://cursor.com/install -fsS | bash' && ssh -o BatchMode=yes ginnoir@valhalla 'bash -lc \"command -v cursor-agent && cursor-agent --version\"'"
|
||||
```
|
||||
Expected: `cursor-agent` installs and prints a version. ginnoir logs in later.
|
||||
|
||||
- [ ] **Step 2: Install the Antigravity CLI (`agy`) from the OFFICIAL Google source**
|
||||
|
||||
Do **not** use blog-derived URLs. Get the exact installer from the official pages first:
|
||||
`https://antigravity.google/download` and `https://antigravity.google/docs/gcli-migration`. Then run
|
||||
the official one-line installer they document, e.g.:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "bash -lc '<official agy installer from antigravity.google/docs>' && ssh -o BatchMode=yes ginnoir@valhalla 'bash -lc \"command -v agy && agy --version\"'"
|
||||
```
|
||||
Expected: `agy` (Go binary, ideal for headless SSH) installs and prints a version. Auth later via
|
||||
keyring/Google sign-in or `ANTIGRAVITY_TOKEN`.
|
||||
|
||||
- [ ] **Step 3: Confirm each agent answers in headless mode (after ginnoir logs in)**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "bash -lc 'claude -p \"say PONG\"; codex exec \"say PONG\"; cursor-agent -p --output-format json --trust \"say PONG\"; agy -p \"say PONG\"'"
|
||||
```
|
||||
Expected: each prints PONG-ish output. **Cursor caveat:** `-p` has a known hang bug — always pass
|
||||
`--output-format json` and wrap with a timeout (`timeout 120 cursor-agent ...`).
|
||||
|
||||
- [ ] **Step 4: Extend acp-skill routing (or add a generic shell-agent skill)**
|
||||
|
||||
Read `~/.hermes/skills/hermes-acp-orchestrator/SKILL.md` to see if `agent=` routing is extensible.
|
||||
- **If extensible:** add `cursor` and `antigravity` targets mapping to the Step 3 invocations
|
||||
(with the cursor timeout + json flags), honoring the `delegation:` `external_timeout_seconds: 900`
|
||||
/ `external_max_output_chars: 24000` caps.
|
||||
- **If not:** add `~/.hermes/skills/shell-agent/SKILL.md` exposing **one** tool
|
||||
`delegate(agent, goal)` that shells out to claude/codex/cursor/agy with the caps + cursor guard.
|
||||
One tool keeps the surface within the tool-budget.
|
||||
Then restart the gateway:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "sudo systemctl restart hermes-gateway.service && sleep 5 && systemctl is-active hermes-gateway.service"
|
||||
```
|
||||
|
||||
- [ ] **Step 5: End-to-end smoke-test each delegation target**
|
||||
|
||||
Run one delegated task per agent (e.g. `agent=cursor`, `agent=antigravity`) and confirm output is
|
||||
captured under the cap. Record any that hang/auth-fail for follow-up.
|
||||
|
||||
- [ ] **Step 6: Checkpoint**
|
||||
|
||||
No repo commit (host-side). Document the four-target fabric + cursor caveat in `memory/hermes-extensions.md`.
|
||||
|
||||
---
|
||||
|
||||
## Task 11: (OPTIONAL) Context efficiency — llmtrim on the cloud-delegation path
|
||||
|
||||
> Opt-in. Start where the win is unambiguous and local-risk-free: trimming the **cloud** delegation
|
||||
> agents' traffic (Claude Code/Codex/Cursor → Anthropic/OpenAI). Defer the llama-swap-fronting idea
|
||||
> until validated. `rtk-hermes` (shell-output trimming) is a separate lighter opt-in.
|
||||
|
||||
**Files:**
|
||||
- Host: llmtrim service + `HTTPS_PROXY` env for the delegation agents.
|
||||
|
||||
- [ ] **Step 1: Install llmtrim and run setup**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "bash -lc 'npm install -g @llmtrim/cli@latest && llmtrim setup' 2>&1 | tail -20"
|
||||
```
|
||||
Expected: installs; `setup` installs the name-constrained CA + background proxy. **Review the MITM-CA
|
||||
trust implication first** — it's name-constrained to LLM API domains, but it's still a CA on the host.
|
||||
|
||||
- [ ] **Step 2: Point the cloud delegation agents through it; measure**
|
||||
|
||||
Ensure the delegation agents inherit `HTTPS_PROXY` (llmtrim sets this). Run a representative delegated
|
||||
task via Claude Code/Codex and compare token counts / cost before vs after (llmtrim reports savings).
|
||||
Keep only if the reduction is real with no quality loss.
|
||||
|
||||
- [ ] **Step 3: (Later, separate) Evaluate llama-swap fronting + rtk-hermes**
|
||||
|
||||
Document — do not implement here — the two deferred ideas: (a) llmtrim in front of `172.20.0.1:8090`
|
||||
via `LLMTRIM_EXTRA_HOSTS` to shrink prompts and speed Pascal prefill (needs validation; unproven for
|
||||
local OpenAI-compatible backends); (b) `rtk-hermes` (`pre_tool_call` shell rewrite) if the `rtk`
|
||||
binary is available on Ubuntu.
|
||||
|
||||
- [ ] **Step 4: Checkpoint**
|
||||
|
||||
No repo commit. Record the decision + measured savings (or rejection) in `memory/hermes-extensions.md`.
|
||||
`llmtrim uninstall` fully reverses the proxy + CA if rejected.
|
||||
|
||||
---
|
||||
|
||||
# PHASE 3 — UI trial: stand up BOTH, keep the winner
|
||||
|
||||
> Decision resolved (spec §6.1): trial `hermes-ui` (Task 7) **and** `hermes-workspace` (Task 8) in
|
||||
> parallel, compare head-to-head against the bundled webui (Task 9), keep one and tear down the
|
||||
> rest. `mission-control` is skipped.
|
||||
|
||||
## Task 7: Trial `hermes-ui` (lightweight, no build)
|
||||
|
||||
**Files:**
|
||||
- Host: clone at `/storage1/hermes/workspace/clones/hermes-ui`; optional `hermes-ui.service` (host unit) or a tiny container; Caddy block if exposed.
|
||||
|
||||
- [ ] **Step 1: Clone and run the stdlib proxy against the live gateway**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "git -C /storage1/hermes/workspace/clones clone https://github.com/pyrate-llama/hermes-ui && cd /storage1/hermes/workspace/clones/hermes-ui && (~/.hermes/hermes-agent/venv/bin/python3 serve_lite.py >/tmp/hermes-ui.log 2>&1 &) && sleep 3 && curl -fsS http://127.0.0.1:3333/hermes-ui.html | head -5"
|
||||
```
|
||||
Expected: the proxy starts on :3333 (defaults to gateway `127.0.0.1:8642`, which matches your deployment), and the HTML serves. If your gateway port differs, edit the `HERMES` variable at the top of `serve_lite.py` (no env var exists).
|
||||
|
||||
- [ ] **Step 2: Expose it on the LAN for evaluation (don't finalize yet)**
|
||||
|
||||
Bind the proxy to the host IP so Caddy can reach it, add a temporary internal-only Caddy block, and
|
||||
keep it running for the Task 9 comparison:
|
||||
```caddy
|
||||
hermes-ui.ginnoir.com {
|
||||
import internal_only
|
||||
reverse_proxy 172.20.0.1:3333
|
||||
}
|
||||
```
|
||||
Run `serve_lite.py` bound appropriately (edit its bind host if it defaults to `127.0.0.1`), regenerate
|
||||
bookmarks, push the Caddyfile change. **Do not** create the persistent `hermes-ui.service` yet — that
|
||||
happens in Task 9 only for the winner.
|
||||
|
||||
- [ ] **Step 3: Checkpoint**
|
||||
|
||||
hermes-ui is reachable at `https://hermes-ui.ginnoir.com` (LAN) for the head-to-head. Leave the
|
||||
final keep/revert + boot-persistence to Task 9.
|
||||
|
||||
---
|
||||
|
||||
## Task 8: Deploy `hermes-workspace` as a stack (Class B) — for evaluation
|
||||
|
||||
**Files:**
|
||||
- Create: `stacks/hermes-workspace/docker-compose.yml`, `stacks/hermes-workspace/stack.env`.
|
||||
- Modify: `Caddyfile` (Authentik-gated site block), `bookmarks-domains.html` + `bookmarks-ports.html`.
|
||||
- Host (image): build under `/storage1/hermes/workspace/clones/hermes-workspace`.
|
||||
|
||||
- [ ] **Step 1: Clone and read its deployment docs (get exact build, ports, env)**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "git -C /storage1/hermes/workspace/clones clone https://github.com/outsourc-e/hermes-workspace && sed -n '1,200p' /storage1/hermes/workspace/clones/hermes-workspace/README.md && ls /storage1/hermes/workspace/clones/hermes-workspace/{Dockerfile,docker-compose*.yml,.env*} 2>&1"
|
||||
```
|
||||
Expected: README + a `Dockerfile`/compose appear. Record the exact image build command, the served
|
||||
port, and the env var(s) that point the frontend at the gateway (`:8642`) and dashboard (`:9119`).
|
||||
**Note the swarm caveat for Task 9:** Swarm Mode (tmux worker pools) can't parallelize inference on
|
||||
one P100 — evaluate the workspace/observability features, not swarm.
|
||||
|
||||
- [ ] **Step 2: Resolve container→host-service reachability**
|
||||
|
||||
hermes-workspace (a container) must reach the host's gateway `:8642` and dashboard `:9119`. Check
|
||||
what interface those bind to:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "ss -ltnp | grep -E ':8642|:9119'"
|
||||
```
|
||||
Expected: shows the bind address. **If bound to `127.0.0.1`**, the container can't reach them — pick
|
||||
one: (a) add `extra_hosts: ["host.docker.internal:host-gateway"]` and target `host.docker.internal`,
|
||||
or (b) rebind the Hermes services to the docker-bridge host IP `172.20.0.1` (config change + gateway
|
||||
restart, with backup). Default recommendation: **(a)** (no Hermes config change; reversible).
|
||||
|
||||
- [ ] **Step 3: Build the image on-host**
|
||||
|
||||
Run (use the build command discovered in Step 1; tag locally since there's no published image):
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "cd /storage1/hermes/workspace/clones/hermes-workspace && docker build -t hermes-workspace:local . 2>&1 | tail -20 && docker image ls hermes-workspace:local"
|
||||
```
|
||||
Expected: `hermes-workspace:local` is built and listed.
|
||||
|
||||
- [ ] **Step 4: Write the stack compose**
|
||||
|
||||
Create `stacks/hermes-workspace/docker-compose.yml` (adjust the served port and gateway/dashboard env
|
||||
keys to Step 1's findings; this uses host.docker.internal per Step 2 option (a)):
|
||||
```yaml
|
||||
# hermes-workspace stack — full web command center for the Hermes agent (trial).
|
||||
# No published image: built on-host as hermes-workspace:local (see plan Task 8).
|
||||
# Human-facing UI → Authentik-gated. Reaches host gateway :8642 + dashboard :9119
|
||||
# via host.docker.internal.
|
||||
services:
|
||||
hermes-workspace:
|
||||
image: hermes-workspace:local
|
||||
container_name: hermes-workspace
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- "com.centurylabs.watchtower.enable=false"
|
||||
env_file:
|
||||
- stack.env
|
||||
networks: [edge]
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
ports:
|
||||
- "172.20.0.1:8088:8088"
|
||||
|
||||
networks:
|
||||
edge:
|
||||
external: true
|
||||
```
|
||||
|
||||
- [ ] **Step 5: Write `stack.env` (gateway/dashboard targets; LF endings)**
|
||||
|
||||
Create `stacks/hermes-workspace/stack.env` using the real env keys from Step 1, e.g.:
|
||||
```
|
||||
HERMES_GATEWAY_URL=http://host.docker.internal:8642
|
||||
HERMES_DASHBOARD_URL=http://host.docker.internal:9119
|
||||
PORT=8088
|
||||
```
|
||||
Verify LF endings before committing.
|
||||
|
||||
- [ ] **Step 6: Add an Authentik-gated Caddy block**
|
||||
|
||||
Unlike camofox (machine-to-machine), this is a human UI → gate with Authentik forward_auth (Pattern B):
|
||||
```caddy
|
||||
workspace.ginnoir.com {
|
||||
import internal_only
|
||||
route {
|
||||
import authentik_outpost
|
||||
import authentik_forward_auth
|
||||
reverse_proxy hermes-workspace:8088
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 7: Deploy and verify**
|
||||
|
||||
Run:
|
||||
```powershell
|
||||
./scripts/gen-bookmarks.ps1
|
||||
git add stacks/hermes-workspace/ Caddyfile bookmarks-domains.html bookmarks-ports.html
|
||||
git commit -m "feat(hermes-workspace): trial command-center stack (eval vs hermes-ui)"
|
||||
git push
|
||||
```
|
||||
Register the stack in Portainer if new, then:
|
||||
```bash
|
||||
ssh -o BatchMode=yes ginnoir@valhalla "docker ps --filter name=hermes-workspace --format '{{.Names}} {{.Status}}' && curl -fsS http://172.20.0.1:8088/ | head -5"
|
||||
```
|
||||
Expected: container `Up`; the workspace HTML serves; logging into `https://workspace.ginnoir.com`
|
||||
via Authentik shows live chat/memory/skills wired to your gateway.
|
||||
|
||||
- [ ] **Step 8: Checkpoint**
|
||||
|
||||
Repo changes committed (Step 7). Leave the keep/tear-down decision to Task 9.
|
||||
|
||||
---
|
||||
|
||||
## Task 9: Head-to-head UI decision — keep one, tear down the rest
|
||||
|
||||
**Files:**
|
||||
- Modify (on tear-down): `Caddyfile`, `stacks/...` (remove the loser), bookmarks; host unit for the winner.
|
||||
|
||||
- [ ] **Step 1: Compare bundled webui vs hermes-ui vs hermes-workspace**
|
||||
|
||||
Use all three live for representative work (chat/streaming, tasks/kanban, files, terminal, skills,
|
||||
MCP browser, cron, memory, health). Score against: does it surface your curated tools cleanly, does
|
||||
it stay responsive against the P100's latency, and does it add real value over the bundled webui.
|
||||
Record the verdict in the vault.
|
||||
|
||||
- [ ] **Step 2: Make the winner permanent**
|
||||
|
||||
- If **hermes-ui** wins: create host unit `hermes-ui.service` (host-managed, like `obsidian.service`
|
||||
— NOT in this repo), `After=hermes-gateway.service`, `Restart=on-failure`; keep its Caddy block.
|
||||
- If **hermes-workspace** wins: keep its stack + Authentik block as-is.
|
||||
- If **bundled webui** wins: keep status quo.
|
||||
|
||||
- [ ] **Step 3: Tear down the losers (reversible, clean)**
|
||||
|
||||
- Remove the hermes-workspace stack if it lost: delete `stacks/hermes-workspace/`, its Caddy block,
|
||||
regenerate bookmarks, commit + push, then delete the stack in Portainer and
|
||||
`docker rm -f hermes-workspace`, `docker image rm hermes-workspace:local`.
|
||||
- Stop/remove hermes-ui if it lost: `pkill -f 'serve_lite[.]py'` (bracket trick), remove its Caddy
|
||||
block + clone, commit the Caddyfile change.
|
||||
|
||||
- [ ] **Step 4: Checkpoint**
|
||||
|
||||
One UI kept and documented in memory + vault; losers fully removed; repo reflects the final state.
|
||||
|
||||
---
|
||||
|
||||
## Self-Review (completed)
|
||||
|
||||
- **Spec coverage:** Original 7 repos — acp-skill (T2), curator-evolver (T3), camofox (T5),
|
||||
eagle-eye (T6), hermes-ui (T7), hermes-workspace (T8 deploy) + keep-one decision (T9);
|
||||
mission-control (skipped per spec §2.5/§5, intentional). **Ecosystem expansion (spec §7)** —
|
||||
hermes-motif (T3b), hermes-web-search-plus (T5b), delegation fabric for cursor+antigravity (T10),
|
||||
optional llmtrim/rtk context efficiency (T11). Claude Code + Codex install is **done** (T1 Step 3).
|
||||
Phase ordering, single-P100 discipline, host-vs-repo boundary, provenance (official installers
|
||||
only — Antigravity URL verified to `antigravity.google`), reversibility, and the §6 decisions are
|
||||
all reflected.
|
||||
- **Placeholders:** None of the prohibited kinds. Where a third-party command form can't be verified
|
||||
remotely (e.g. exact `hermes` subcommand spelling, acp-skill install mechanism, response field
|
||||
names), the plan's **first step is a concrete "clone + read the README/SKILL.md" command** that
|
||||
resolves it before use — a real action with expected output, not a TBD.
|
||||
- **Consistency:** Paths and names are consistent throughout (`~/.hermes/skills`, `~/.hermes/plugins/curator-evolver`, `camofox-browser:local`, port 9377, gateway 8642, `172.20.0.1` host-IP publish pattern, `sudo systemctl restart hermes-gateway.service`).
|
||||
- **Decision gates:** Phases 2–3 are clearly gated on spec §6 and must not start before ginnoir answers.
|
||||
@@ -0,0 +1,346 @@
|
||||
# Hermes Ecosystem Integration — Triage & Design
|
||||
|
||||
**Date:** 2026-06-27
|
||||
**Author:** Claude (overnight autonomous research for ginnoir; for morning review)
|
||||
**Status:** Draft — awaiting ginnoir's decisions on the flagged items below
|
||||
|
||||
---
|
||||
|
||||
## 0. TL;DR for the morning
|
||||
|
||||
You asked me to research seven Hermes-ecosystem repos and plan how each fits. I verified all
|
||||
seven are real and active, mapped each against your **actual** Hermes deployment (host systemd
|
||||
install on valhalla, llama-swap/P100 backend, ~29-tool curated MCP surface, Codex + Claude Code
|
||||
also installed), and triaged them into adopt / trial / decide / skip.
|
||||
|
||||
**Recommended path:**
|
||||
|
||||
| Phase | Repo | Verdict | Why |
|
||||
|---|---|---|---|
|
||||
| **1** | `hermes-agent-acp-skill` | **ADOPT** | Pure skill drop-in; lets the local 20B offload hard work to Codex/Claude Code, which you already run. Highest leverage, lowest risk. |
|
||||
| **1** | `hermes-curator-evolver` | **ADOPT (dry-run first)** | Closes Hermes' self-improvement loop; read-only by default; aligns with your curation habit. |
|
||||
| **2** | `camofox-browser` | **ADOPT (new homelab stack)** | Gives the local agent real web browsing; clean Docker/Caddy fit; independent of Hermes internals. |
|
||||
| **2** | `eagle-eye` | **TRIAL / DEFER** | Solves the exact tool-overload pain you already hit — but very early (5★, 1 commit) and carries a required Chinese-tokenizer dep. Trial behind a flag; don't depend on it. |
|
||||
| **3** | `hermes-ui` | **ADOPT (trial)** | Single-HTML + stdlib proxy; stood up next to the bundled webui to evaluate. |
|
||||
| **3** | `hermes-workspace` | **ADOPT (trial)** | Full command center; stood up in parallel to compare head-to-head, then keep one. Swarm Mode won't parallelize on one P100 — value is the workspace/observability features. |
|
||||
| **3** | `mission-control` | **SKIP** | Not Hermes-native (built for OpenClaw/CrewAI/LangGraph/AutoGen). Redundant with the two Hermes UIs. |
|
||||
|
||||
**Decisions — RESOLVED 2026-06-27 (see Section 6):** (1) trial **both** UIs, keep the winner;
|
||||
(2) curator-evolver stays **report-only** for now; (3) **trial eagle-eye** — it's the only direct
|
||||
skill-router in the ecosystem, no more-mature equivalent exists; (4) wire camofox as a **minimal
|
||||
2-tool skill**.
|
||||
|
||||
---
|
||||
|
||||
## 1. The anchor: your current Hermes deployment
|
||||
|
||||
Everything below is sized against what you actually run (from project memory, verified against the
|
||||
repo and host conventions):
|
||||
|
||||
- **Hermes Agent v0.17.0 (NousResearch)** runs on the **valhalla host**, not in Docker — systemd
|
||||
units `hermes-gateway.service`, `hermes-dashboard.service`, `hermes-webui.service`. Editable
|
||||
install at `~/.hermes/hermes-agent/`; config at `~/.hermes/config.yaml`; CLI `~/.local/bin/hermes`.
|
||||
Workspace at `/storage1/hermes/workspace/`.
|
||||
- **Backend:** llama-swap (`stacks/llm`, Portainer id 34) on a single **Tesla P100 16GB**, serving
|
||||
one GGUF at a time, `--parallel 1`, 64k ctx, default `gpt-oss-20b`. OpenAI API at
|
||||
`http://172.20.0.1:8090/v1`.
|
||||
- **MCP surface deliberately curated to ~29 tools** because gpt-oss-20b drowns in tool overload.
|
||||
This is the single most important constraint for everything below: **the local model is weak at
|
||||
selection under load, and the GPU runs one model, one sequence at a time.**
|
||||
- **You also run Codex (`~/.codex`) and Claude Code**, kept in sync with your Claude global config.
|
||||
This is what makes the ACP delegation skill genuinely useful rather than theoretical.
|
||||
|
||||
### 1.1 Two integration classes (this drives the whole plan)
|
||||
|
||||
- **Class A — host-side Hermes extensions** (plugins & skills): live in `~/.hermes/` on valhalla,
|
||||
applied by SSH + `hermes ...` + gateway restart. **These are NOT homelabstack repo content.**
|
||||
They are host-managed exactly like the rustdesk/obsidian/xvfb units — tracked in project memory
|
||||
and the Obsidian vault, not committed here. Fully reversible (config backups + plugin uninstall).
|
||||
→ `hermes-agent-acp-skill`, `hermes-curator-evolver`, `eagle-eye`.
|
||||
- **Class B — Docker services**: become `stacks/<name>/` entries, deployed via the normal
|
||||
Gitea-poll path, fronted by Caddy (`internal_only` + Authentik), secrets in `stack.env`,
|
||||
infra images pinned out of Watchtower.
|
||||
→ `camofox-browser`, and (if adopted) `hermes-ui` / `hermes-workspace` / `mission-control`.
|
||||
|
||||
---
|
||||
|
||||
## 2. Per-repo analysis
|
||||
|
||||
### 2.1 `hermes-agent-acp-skill` (Rainhoole) — **ADOPT, Phase 1**
|
||||
|
||||
- **What:** A Hermes *skill* (`SKILL.md` + `README.md`, MIT) implementing `delegate_task()` —
|
||||
multi-agent delegation across Hermes internal subagents, **Codex**, and **Claude Code**. Handles
|
||||
agent routing (`agent=...`), context isolation, and safety controls (recommended 900 s external
|
||||
timeout, 24,000-char output cap).
|
||||
- **Fit:** Strong and specific. Your local model is gpt-oss-20b — fine for orchestration and light
|
||||
tasks, weak for real implementation/review. This skill lets Hermes *route the hard parts to the
|
||||
frontier CLIs you already have installed and configured*. It turns the weak local brain into a
|
||||
dispatcher.
|
||||
- **Risk:** Low. It's a skill file, not running code you didn't write — but it *invokes external
|
||||
agents*, so the real work is verifying Codex/Claude Code are launchable from the Hermes service
|
||||
environment (PATH, auth, non-interactive flags) and that timeouts/output caps are sane.
|
||||
- **Implementation sketch:** Drop into `~/.hermes` skills dir (or `hermes skills install` if the
|
||||
repo packages it that way — verify on the host); set delegation targets to the Codex + Claude
|
||||
Code invocations; restart gateway; smoke-test a trivial delegated task end-to-end.
|
||||
|
||||
### 2.2 `hermes-curator-evolver` (pingchesu) — **ADOPT, dry-run first, Phase 1**
|
||||
|
||||
- **What:** Local-first Hermes *plugin* (Python 3.11, SQLite, `hermes plugins install`). Mines
|
||||
evidence from sessions/tool-calls, ranks skill-improvement candidates, and generates **dry-run,
|
||||
reviewable** proposals. **Read-only by default; mutations require explicit `--approve`.** Only
|
||||
touches *local agent-created* skills — skips bundled, hub-installed, and external skills. Size
|
||||
guardrails, backup/rollback manifests, optional Qwen-embeddings + BGE-reranker for semantic
|
||||
ranking, native scheduler (systemd) integration.
|
||||
- **Fit:** This *is* Hermes' "self-improving" thesis made operational, and it matches how you
|
||||
already work (curate, gate, keep things reversible). The default posture (report-only, dry-run,
|
||||
human-review queue) is exactly the safe on-ramp.
|
||||
- **Risk / caveats:**
|
||||
- It writes to skills with `--approve`. **Recommendation: run report-only / dry-run indefinitely
|
||||
at first**; promote to `--approve` only after you've seen a few proposal batches you'd have
|
||||
accepted anyway.
|
||||
- Optional embeddings/reranker want a model. **Do not load them onto the P100** alongside
|
||||
gpt-oss — the GPU is single-model/`--parallel 1`. Run ranking on **CPU**, or skip the dense
|
||||
layer initially (BM25/FTS ranking is enough to start).
|
||||
- Schedule the mining pass **off-peak** via a systemd timer so it never contends with live
|
||||
inference.
|
||||
- **Implementation sketch:** `hermes plugins install` on the host; point it at the session store;
|
||||
run one manual `collect`→`rank`→`report` cycle by hand; inspect the review queue; only then wire
|
||||
a nightly systemd timer in report-only mode.
|
||||
|
||||
### 2.3 `eagle-eye` (willingning-coder) — **TRIAL / DEFER, Phase 2**
|
||||
|
||||
- **What:** Zero-invasive skill *pre-filter* plugin. Before the LLM call, narrows 50+ skills to the
|
||||
top ~5 via a 5-layer cascade (hard triggers → FTS5/BM25 → synonyms → dense embeddings → RRF
|
||||
fusion), degrading gracefully when optional deps are absent. "Not matching is a valid result."
|
||||
- **Fit (conceptual):** Excellent — this is the **skill-side analog of the MCP tool-overload fix
|
||||
you already did**. Fewer, better skill candidates in the prompt = better selection by a weak
|
||||
model + less Pascal prefill. If it works, it directly improves gpt-oss-20b's behavior.
|
||||
- **Risk / caveats (why it's a trial, not an adopt):**
|
||||
- **Maturity:** 5 stars, single commit. Early. Treat as experimental.
|
||||
- **Dependency smell:** `jieba` (Chinese tokenization) is a *required* dep; your skill library is
|
||||
English. Works, but signals the author's primary use case differs from yours — watch for
|
||||
English-tokenization edge cases and maintenance drift.
|
||||
- Same P100 rule: keep its dense-embedding layer on **CPU** or disabled; lean on L1–L2
|
||||
(deterministic + BM25) first.
|
||||
- **Implementation sketch:** Install behind an easy on/off switch on the host; A/B a handful of
|
||||
representative prompts with it on vs off; keep it **only if** measured skill-selection quality
|
||||
improves. Do not let any workflow depend on it.
|
||||
|
||||
### 2.4 `camofox-browser` (jo-inc) — **ADOPT as a homelab stack, Phase 2**
|
||||
|
||||
- **What:** Stealth headless browser (Camoufox/Firefox) exposing a **REST API for AI agents** —
|
||||
anti-fingerprinting, element-reference interaction (`e1`,`e2`), session isolation, proxy/GeoIP,
|
||||
YouTube transcripts, Docker/Fly/Railway deploy. 7.2k★, actively maintained. **No Hermes coupling**
|
||||
— it's a generic tool backend.
|
||||
- **Fit:** Clean Class-B homelab fit and a real capability gap-filler: your agent currently has
|
||||
freshrss + obsidian but no general web browser. As `stacks/camofox`, internal-only behind Caddy,
|
||||
it gives Hermes (and Codex/Claude) reliable browsing.
|
||||
- **Risk / caveats:**
|
||||
- It's anti-detection tooling — appropriate for personal research; **keep it strictly LAN/SSO-gated
|
||||
(`import internal_only` + Authentik)** and off the public internet. New attack surface; pin the
|
||||
image and read the Dockerfile before running.
|
||||
- Heavier service (~300 MB Camoufox binary, Firefox). Fine on valhalla, but it's not free.
|
||||
- **Wiring to Hermes:** either a thin MCP shim around its REST API, or a Hermes skill that curls
|
||||
it. Given your tool-overload sensitivity, expose it as **one or two** high-level tools (e.g.
|
||||
`browse(url)`, `search(query)`), not its full surface.
|
||||
- **Implementation sketch:** New `stacks/camofox/docker-compose.yml` (bind config to `/config/camofox`,
|
||||
blobs/cache to `/storage1/labdata/camofox`, join `edge`), `stack.env`, a Caddy block
|
||||
(`camofox.ginnoir.com`, `import internal_only`), regenerate bookmarks, push. Then add the minimal
|
||||
Hermes tool/skill wrapper on the host and restart the gateway.
|
||||
|
||||
### 2.5 The three dashboards — pick **at most one** (Phase 3, DECISION)
|
||||
|
||||
You already run the bundled `hermes-webui.service`, so a UI is an *upgrade*, not a gap. These three
|
||||
overlap heavily; adopting more than one is waste.
|
||||
|
||||
| | `hermes-ui` (pyrate-llama) | `hermes-workspace` (outsourc-e) | `mission-control` (builderz-labs) |
|
||||
|---|---|---|---|
|
||||
| Stars | 173 | 5.9k | 5.4k |
|
||||
| Stack | 1 HTML file + Python **stdlib** proxy (`serve_lite.py`, :3333 → gateway :8642) | React/TS/**Vite build**, Node 22+, → gateway :8642 + dashboard :9119 | Next.js 16 / React 19, better-sqlite3 |
|
||||
| Hermes-native? | **Yes** | **Yes** (best with vanilla hermes-agent) | **No** (OpenClaw/CrewAI/LangGraph/AutoGen/Claude SDK) |
|
||||
| Effort to host | **Trivial** (no build) | Medium (build → container/stack) | Medium + **adapter work** |
|
||||
| Headline features | chat, tasks/kanban, files, terminal, skills, MCP browser, cron, memory, health | all of the above + ops dashboards, "Conductor" missions, **Swarm Mode (tmux worker pools)** | 32 panels, RBAC, spend/trust scoring, multi-framework |
|
||||
| Verdict | **Trial first** | **Consider as a proper stack later** | **Skip / defer** |
|
||||
|
||||
- **`hermes-ui` — recommended first move.** Lowest cost to evaluate a richer UI. Can run as a tiny
|
||||
host service or a minimal container next to the bundled webui; no build pipeline. If it's better
|
||||
than the bundled webui, keep it; if not, delete one file.
|
||||
- **`hermes-workspace` — the ambitious option.** Genuinely the most capable, best run as a real
|
||||
`stacks/hermes-workspace` Docker build behind Caddy + Authentik. **Caveat to flag:** its
|
||||
marquee **Swarm Mode (parallel tmux worker pools) cannot actually parallelize inference on your
|
||||
setup** — the single P100 runs one model with `--parallel 1`, so "swarm" workers serialize on the
|
||||
GPU (or must use a different/remote backend per worker). Adopt for the workspace/observability
|
||||
features, not for swarm, unless/until you add GPU capacity or point swarm workers at cloud
|
||||
providers.
|
||||
- **`mission-control` — skip unless requirements change.** It's framework-agnostic and **not
|
||||
Hermes-native** — using it means writing a Hermes adapter for a dashboard whose job the two
|
||||
Hermes-native UIs already do. Only worth it if you later want a single ops plane across *multiple*
|
||||
agent frameworks (you don't run those today).
|
||||
|
||||
---
|
||||
|
||||
## 3. Recommended phased rollout
|
||||
|
||||
**Phase 1 — host-side, reversible, high-leverage (no repo changes):**
|
||||
1. `hermes-agent-acp-skill` — install skill, wire Codex + Claude Code delegation targets, smoke-test.
|
||||
2. `hermes-curator-evolver` — install plugin in **report-only/dry-run**, manual cycle, then nightly
|
||||
systemd timer (report-only). CPU ranking; no P100 embeddings.
|
||||
|
||||
**Phase 2 — new capability + experiment:**
|
||||
3. `camofox-browser` — new `stacks/camofox` (Class B), Caddy internal-only + Authentik, minimal
|
||||
Hermes tool wrapper.
|
||||
4. `eagle-eye` — host-side trial behind an on/off switch; A/B skill-selection; keep only if it helps.
|
||||
|
||||
**Phase 3 — UI decision (your call):**
|
||||
5. Trial `hermes-ui` alongside the bundled webui. Evaluate `hermes-workspace` as a stack if the
|
||||
workspace features justify the build. Skip `mission-control`.
|
||||
|
||||
Each phase is independently shippable and independently reversible. Stop after any phase.
|
||||
|
||||
---
|
||||
|
||||
## 4. Cross-cutting concerns (apply to every adoption)
|
||||
|
||||
- **Single-P100 discipline.** One GPU, one model, `--parallel 1`. Anything implying parallel or
|
||||
extra model loads — curator embeddings, eagle-eye dense layer, workspace swarm — must run on
|
||||
**CPU**, **off-peak**, or **not at all**. Never co-resident with gpt-oss on the P100.
|
||||
- **Host vs repo boundary.** Class-A extensions are host-managed in `~/.hermes/` (document in memory
|
||||
+ vault, like the rustdesk/obsidian units). Only Class-B services touch this repo. Don't
|
||||
accidentally commit host config here.
|
||||
- **Tool/skill surface minimalism.** The whole reason your MCP is curated to ~29 tools. Expose new
|
||||
capabilities (camofox, delegation) as a *few high-level* tools, not raw surfaces, or you reintroduce
|
||||
the overload you fixed.
|
||||
- **Provenance & safety.** Several repos are small/young (eagle-eye 1 commit; acp-skill 1 commit).
|
||||
**Read the code before running it**, especially anything that writes skills (curator) or executes
|
||||
shell / external agents (acp-skill, camofox). **Pin to a reviewed commit/tag**; keep stack images
|
||||
out of Watchtower auto-update.
|
||||
- **Reversibility.** Back up `~/.hermes/config.yaml` before each Class-A change (you already do this);
|
||||
snapshot before promoting curator to `--approve`.
|
||||
- **Security posture.** Class-B services: `import internal_only` + Authentik, secrets in `stack.env`
|
||||
(LF endings), never public.
|
||||
|
||||
---
|
||||
|
||||
## 5. What I am explicitly NOT proposing
|
||||
|
||||
- Not running curator-evolver in `--approve` (auto-skill-editing) mode out of the gate.
|
||||
- Not loading any second model onto the P100 (no GPU embeddings, no GPU swarm).
|
||||
- Not adopting more than one dashboard.
|
||||
- Not committing host-side Hermes plugins/skills into the homelabstack repo.
|
||||
- Not exposing camofox or any new UI to the public internet.
|
||||
|
||||
---
|
||||
|
||||
## 6. DECISIONS — RESOLVED 2026-06-27
|
||||
|
||||
1. **UI direction → trial BOTH.** Stand up `hermes-ui` *and* `hermes-workspace` in parallel,
|
||||
evaluate head-to-head against the bundled webui, then keep the winner and remove the other.
|
||||
(Phase 3 now builds both.)
|
||||
2. **Curator autonomy → report-only for now.** `hermes-curator-evolver` runs dry-run/report only;
|
||||
no `--approve` / `--apply-low-risk` / `--approve-auto-apply`. Revisit after a trust period.
|
||||
3. **eagle-eye → trial it.** Rationale (ginnoir): wants a large skill library available without
|
||||
weighting every turn — which is exactly eagle-eye's pre-LLM skill-selection job. **Research
|
||||
result:** eagle-eye is the *only* direct skill-router in the Hermes ecosystem (per
|
||||
`awesome-hermes-agent` / Hermes Atlas); the nominal "alternatives" do different jobs —
|
||||
`llmtrim` (compresses tool schemas + MCP output; **complementary**, worth a later look for the
|
||||
tool side), `rtk-hermes` (shell-output compression), `hermes-snow-search` (faster session
|
||||
search), `hermes-motif` (mines traces into micro-skills; a curator-evolver *rival*, not a
|
||||
router). So eagle-eye stands, with the trial caveat (1-commit maturity, `jieba` dep): keep only
|
||||
if it measurably improves selection; run L1+L2 only (no P100 embeddings).
|
||||
4. **camofox wiring → minimal.** A small 2-tool Hermes skill (`browse`, `search`) over the REST
|
||||
API, not the full surface or an MCP shim — protects the curated tool budget.
|
||||
|
||||
All four resolved ⇒ **Phases 1, 2, and 3 are all actionable.** The implementation plan that
|
||||
follows details every phase.
|
||||
|
||||
**Ecosystem expansion (added 2026-06-27, per ginnoir):** while researching eagle-eye alternatives I
|
||||
surveyed the wider Hermes ecosystem and the external-agent landscape. The worthwhile additions and
|
||||
the motif-vs-curator verdict are in **§7**. Claude Code + Codex are **already installed on valhalla**
|
||||
(this session); Cursor + Antigravity are scoped for the delegation fabric.
|
||||
|
||||
---
|
||||
|
||||
## 7. Ecosystem expansion & the delegation fabric (added 2026-06-27)
|
||||
|
||||
### 7.1 `hermes-motif` vs `hermes-curator-evolver` — verdict: **complementary, run both**
|
||||
|
||||
I earlier mis-framed these as rivals. They do **different halves of one loop**:
|
||||
|
||||
- **`hermes-motif` (Saurav0989) — skill DISCOVERY.** Watches tool calls live, finds repeated
|
||||
sequences (same tools, varying args → `{variable}`), and proposes them as **new** `SKILL.md`
|
||||
drafts. **Makes no LLM calls** — pure pattern-mining, so **zero P100 cost**. `auto_install: false`
|
||||
= proposal-only. Zero-to-one skill creation.
|
||||
- **`hermes-curator-evolver` (pingchesu) — skill REFINEMENT.** Improves **existing** agent-created
|
||||
skills from session evidence; bounded, reviewable edits; report-only default; more mature
|
||||
(CI, systemd scheduler, backup/rollback).
|
||||
|
||||
**Fit for you:** your stated goal (eagle-eye rationale) is a *large* skill library without per-turn
|
||||
weight. That's a **skill factory**: **motif manufactures** new skills from what you already do
|
||||
repeatedly → **curator refines** them → **eagle-eye routes** among them at call time. They compose.
|
||||
**Recommendation: run both in proposal/report-only mode.** If you insist on only one to start,
|
||||
**motif** is the lower-risk, higher-immediate-value pick for *growing* a library (no model cost, no
|
||||
edits to existing files) — but there's no reason to drop curator; it's already Phase 1 and free to
|
||||
leave in report-only. Plan adds motif as **Task 3b**.
|
||||
|
||||
### 7.2 `hermes-web-search-plus` — **ADOPT** (pairs with camofox)
|
||||
|
||||
Mature (v2.6.1, MIT, stdlib-only) Hermes plugin: multi-provider web **search** + extraction with
|
||||
intent-aware routing (news/shopping/docs/GitHub/academic/security) and a `research` mode. 14
|
||||
providers, **all keys optional** — works with a single configured provider (free tiers exist: Tavily,
|
||||
Exa, SearXNG self-host, Keenable keyless). **Complements camofox**, doesn't overlap it: search-plus
|
||||
*finds* (cheap API calls), camofox *browses/interacts* (heavy headless Firefox). For a P100-limited
|
||||
local agent, search-plus is the lighter, higher-frequency tool — arguably the one to reach for first;
|
||||
camofox for when a page needs real rendering/interaction. Plan adds it as **Task 5b**, before/with
|
||||
camofox. Install: `hermes plugins install robbyczgw-cla/hermes-web-search-plus --enable`.
|
||||
|
||||
### 7.3 Context-efficiency layer — **OPTIONAL**, helps the Pascal bottleneck
|
||||
|
||||
Your memory notes prefill is the P100 differentiator and context bloat is the enemy. Two opt-in tools:
|
||||
|
||||
- **`llmtrim` (fkiene, MPL-2.0)** — HTTPS-proxy / MCP / CLI that compresses **tool schemas + history
|
||||
+ tool output** before requests (claims −31% input / −74% output tokens, BM25+ context ranking,
|
||||
log-templating). Works with anything honoring `HTTPS_PROXY` (Claude Code, Cursor, Aider). **Two
|
||||
distinct payoffs:** (a) in front of the **cloud delegation agents** (Claude Code/Codex/Cursor →
|
||||
Anthropic/OpenAI) it cuts real $ cost; (b) potentially in front of **llama-swap** (via
|
||||
`LLMTRIM_EXTRA_HOSTS`) to shrink prompts and speed Pascal prefill — needs validation, it's not
|
||||
documented for local OpenAI-compatible backends. Caveat: it installs a name-constrained MITM CA;
|
||||
acceptable but a real trust decision.
|
||||
- **`rtk-hermes` (ogallotti, MIT)** — `pre_tool_call` hook that rewrites shell commands through the
|
||||
`rtk` binary so terminal output arrives pre-filtered (cache-safe; preserves tool schema). Lighter,
|
||||
shell-only. Needs the `rtk` binary on the host (`brew`/Linux build — verify availability).
|
||||
|
||||
**Recommendation:** defer both to an **opt-in Task 11**. Start llmtrim on the *cloud-delegation* path
|
||||
(clear cost win, no local risk) before considering it in front of llama-swap.
|
||||
|
||||
### 7.4 The delegation fabric — claude-code · codex · cursor · antigravity
|
||||
|
||||
Your acp-skill (Task 2) natively routes to `codex`, `claude-code`, and `hermes` subagents. You also
|
||||
want **Cursor** and **Antigravity** in the mix. All four have real **headless** CLIs usable as
|
||||
delegation targets from the valhalla host:
|
||||
|
||||
| Agent | CLI | Headless invocation | Install (official) | Status on valhalla |
|
||||
|---|---|---|---|---|
|
||||
| Claude Code | `claude` | `claude -p` | `curl -fsSL https://claude.ai/install.sh \| bash` → `~/.local/bin/claude` | **Installed** v2.1.195 (login pending) |
|
||||
| Codex | `codex` | `codex exec` / non-interactive | `npm i -g @openai/codex` (Node 22+) | **Installed** v0.142.3 (login pending) |
|
||||
| Cursor | `cursor-agent` | `cursor-agent -p --output-format json --trust` | `curl https://cursor.com/install -fsS \| bash` | Scoped (Task 10) — note: known `-p` hang bug, set `--output-format json` + timeout |
|
||||
| Antigravity | `agy` (ex-Gemini CLI, Go binary, **best for headless SSH**) | `agy -p` / `--headless --approve` | from **official** `antigravity.google/download` + `/docs/gcli-migration` (auth via keyring/Google sign-in or `ANTIGRAVITY_TOKEN`) | Scoped (Task 10) |
|
||||
|
||||
**Wiring approach (Task 10):** acp-skill supports `codex`/`claude-code`/`hermes` out of the box —
|
||||
verify whether its `agent=` routing is **extensible** (read `SKILL.md`). If yes, add `cursor` and
|
||||
`antigravity` targets pointing at the headless invocations above. If not, add a **thin generic
|
||||
"shell-agent" skill** that shells out to any of the four with the timeout/output caps from the
|
||||
`delegation:` config — keeping the exposed tool surface minimal (your standing tool-budget rule).
|
||||
**Alternatives noted, not adopted:** `42-evey/hermes-plugins` ships `evey-bridge` (file inbox/outbox
|
||||
+ MCP bridge to Claude Code) and `evey-delegate-model` (model routing w/ fallback) — heavier,
|
||||
opinionated, unknown maturity; acp-skill is the simpler purpose-built choice. `evey-cost-guard`
|
||||
(Langfuse budget enforcement) becomes worth a look **once cloud delegation is live** and spend
|
||||
matters.
|
||||
|
||||
### 7.5 Updated rollout placement
|
||||
|
||||
- **Phase 1:** + **Task 3b `hermes-motif`** (proposal-only, zero P100 cost).
|
||||
- **Phase 2:** + **Task 5b `hermes-web-search-plus`** (light search, pairs with camofox).
|
||||
- **Phase 2b (new):** **Task 10 delegation fabric** (install cursor + agy, wire all four into
|
||||
acp-skill) and **Task 11 (optional) context efficiency** (llmtrim on the cloud-delegation path;
|
||||
rtk for shell).
|
||||
- **Phase 3:** unchanged (both UIs → keep one).
|
||||
@@ -3,10 +3,10 @@
|
||||
# only one fits in VRAM at a time, so selecting a different model triggers a
|
||||
# brief reload. Default is chosen by Hermes (model.default = gpt-oss-20b).
|
||||
#
|
||||
# All four serve 64k context (Hermes' minimum). Args are the validated Pascal
|
||||
# All serve 64k context (Hermes' minimum). Args are the validated Pascal
|
||||
# config: q8_0 KV (q4_0 V-cache is pathological on GP100), flash-attn on,
|
||||
# --parallel 1 so one sequence gets the full 64k. gpt-oss/gemma4 are natively
|
||||
# >=128k so no YaRN/override-kv needed.
|
||||
# --parallel 1 so one sequence gets the full 64k. gpt-oss/gemma4/ornith are
|
||||
# natively >=128k so no YaRN/override-kv needed.
|
||||
#
|
||||
# Excluded: qwen3-30b-a3b-2507 (Q3) — OOMs at 64k in 16GB, so it can't meet
|
||||
# Hermes' 64k minimum on this GPU.
|
||||
@@ -27,6 +27,15 @@ models:
|
||||
-m /models/gpt-oss-20b-mxfp4.gguf --alias gpt-oss-20b
|
||||
${common}
|
||||
|
||||
"ornith-1.0-9b":
|
||||
# DeepReinforce Ornith-1.0, dense ~9B on Qwen 3.5 (Q5_K_M). MIT. Agentic-coding
|
||||
# tuned: <think> block (-> reasoning_content under --jinja) + Qwen3 XML tool calls.
|
||||
# Native 256k so no YaRN. Recommended sampling: temp 0.6 / top_p 0.95 / top_k 20.
|
||||
cmd: >
|
||||
/app/llama-server --port ${PORT} --host 0.0.0.0
|
||||
-m /models/ornith-1.0-9b-Q5_K_M.gguf --alias ornith-1.0-9b
|
||||
${common}
|
||||
|
||||
"gemma-4-26b-a4b":
|
||||
# gemma4 MoE, 4B active / 26B total (UD-Q3_K_M). Quality-leaning; ~147 tok/s prefill.
|
||||
cmd: >
|
||||
|
||||
Reference in New Issue
Block a user