Architecture · Proposed · 2026-07-10

Heavy Hermes

The full adaptive Hermes harness, backed by Grok 4.3, composing OiMy-quality replies natively — grounded every turn in OiMy's tested knowledge assets, not a persona sketch. Architected so a later swap to a finetuned Gemma 4 is a config change, not a rewrite.

Buildable now · Grok 4.3 variant Verified against oimy-engine (dev :8090) hermes-agent 0.15.2
The core idea

Heavy Hermes is not "paste OiMy's prompts into SOUL.md."

Two hard facts make static injection impossible — and point straight at the right design instead.

Why not just paste

hermes-agent caps SOUL.md at 20,000 characters (CONTEXT_FILE_MAX_CHARS = 20_000, prompt_builder.py:819). The coaching-anchors file alone is 135 KB. And OiMy already solved "too much knowledge for one context" with per-turn retrieval and assembly — tuned, tested, single-sourced. Heavy Hermes should consume that machinery, not duplicate it.

  • A compiled SOUL.md (~18 KB budget) built from small, tagged modules in soul.d/: voice doctrine, anti-sycophancy, coaching foundation, planning, safety, and a grounding protocol — each tagged absorb: finetune or absorb: never.
  • A new engine endpoint POST /context ("grounding pack") that exposes exactly what _call_companion assembles today — entity context, profile, top-K coaching anchors, constraint ledger, Honcho insight — as labeled JSON blocks, per user, per message.
  • A pre_llm_call shell hook in Hermes that fetches the pack every turn and injects it deterministically. This kills the observed failure mode at the root: grounding no longer depends on the model deciding to call a tool.
  • A POST /context/writeback so the engine's learning loops keep learning from turns Hermes composed — otherwise the deep profile goes stale and heavy Hermes slowly lobotomizes the product.
  • The model swap is a manifest recompile + config flip: build_soul.py --target gemma4-ft drops the absorb: finetune modules; everything tagged absorb: never (live family data, ledger, safety) keeps flowing unchanged — and matters more post-swap, because the finetune is trained with those blocks present.
Section 1

The three configurations

Heavy Hermes is the config Bharath's original SOUL.md vision wanted — a frontier model running the full adaptive harness — but fed the tested OiMy content instead of improvising from a persona sketch.

OiMy-as-tool (old default) Light Hermes (built tonight) Heavy Hermes (this doc)
Hermes personaFull SOUL.md (12 KB, "Oi")Gutted to thin routerFull harness persona, restored + modularized
Hermes modelkimi-k2.6kimi-k2.6x-ai/grok-4.3
Who composes the replyOiMy engine — when Hermes calls itOiMy engine, alwaysHermes / Grok itself
GroundingEngine-internalEngine-internalGrounding pack pulled per turn
Failure modeHermes improvises instead of calling the toolHarness capability wastedVoice/asset drift — mitigated by single-sourcing (§5)
Engine's roleFull productFull productKnowledge + memory service
Learning loopSees every turnSees every turnSees every turn via writeback

It is also, not incidentally, a teacher-model data factory: heavy-Hermes transcripts (Grok 4.3 + full grounding) are close to ideal supervised examples for the Gemma 4 finetune — the same teacher/student doctrine applied one level up.

Section 2

Inventory: OiMy's knowledge layers, categorized

Every asset is one of three kinds. The classification decides whether a finetune can eventually absorb it — or whether it must be injected live, forever.

A · static, prompt-injectable — candidate for absorption A′ · static but never dropped — safety, protocol, live-fact discipline B · genuinely dynamic runtime data — always injected live

"Absorbable" is defined against a specific finetune — the gold-standard multi-day dataset (17 families, 42-day arcs, ~874 trainable rows). Two properties drive the whole categorization: training rows are production-context-shaped (the finetune is trained to consume runtime context blocks, not operate without them), and the 17 families are synthetic — no real family's data is, or ever will be, in the weights. Every real roster, profile, ledger and history is category (B) forever.

2.1Coaching anchors — 35 frameworks
A · delivered via retrieval
prompts/deepseek-coaching-anchors-v1.txt
v2.8, 35 frameworks (Becky Kennedy, Siegel/Bryson, Gottman, Perel, Walker, Huberman, addiction dual-track, GLP-1…). Each anchor is trigger → core insight → delivery variants keyed to DISC type + attachment style → "if prior approach didn't land" → what not to do. Anchor content is what a finetune should absorb; the retrieval discipline (threshold 0.50, top-3, session demotion) is engine machinery to reuse via /context.
135 KB→ /context retrieval (top-3, 12 KB cap)
2.2Companion voice / personality prompt
A
prompts/gemma4_12b_companion_combined_v2.txt
The most refined behavioral spec in the system, 385 lines: terse-in→answer-first vs sharing-in→warmth-first message reading, emotions-first, venting protocol, two-turn pacing, personality gating, opener bans, structure/length doctrine, memory-weaving, never-break-character redirects. For Grok 4.3, a distilled ~8 KB version becomes the core SOUL module.
40 KB → 8 KB distilled→ SOUL module 10-voice
2.3Original Hermes SOUL.md persona
A / A′
SOUL.md.bak.pre-routing-override-20260710
Oi's inner life, anti-sycophancy hard rules, warmth calibration, relationship modes 1–4, Telegram-native behavior, identity discipline, proactive-message rules. Overlaps ~60% with 2.2 but written for a harness-holder. Merge, don't keep both: anti-sycophancy, relationship modes, Telegram behavior, identity survive as modules; emotional-response doctrine defers to 2.2.
12 KB→ modules 00-identity, 40-telegram, 50-harness
2.4Planner / constraint design principles
A + B (split)
archetypes/planner.py
(A) Planning doctrine (~2 KB module): every plan option exposes constraints_satisfied, constraints_unknown, and risks_or_checks; live local facts (hours, prices, availability) always flagged "verify before relying." (B) The live constraint ledger: h30.update_constraint_ledger() extracts constraints from the message and injects them as a hard-rule block — per-user, per-session, always runtime.
79 KB, 10 skills→ module 30-planning + /context ledger
2.5Deep inferred profile system
B · outputs
archetypes/inference.py + prompts/deep-inference-v6.txt
Pipeline stays engine-side (run by claude-opus-4.8). Its outputs are pure (B) — exactly what can never be finetuned. _build_profile_context() assembles, capped 2,500 chars: [Facts] Tier-1 entity facts, [Psych] DISC type / Hughes need / attachment style (the keys the anchors' delivery variants switch on), [Inferences] Tier-3 top-5 with confidence, [H3.0] engagement + life-domain, [Failed Approaches]. Plus entity roster (never-invent-names rule), Honcho insight, current topic, open threads.
2.5 KB/user→ /context [PROFILE], [FAMILY]
2.6H3.0 engine — hints vs state
A hints / B state
archetypes/h30.py
Quadrant/level inference (Grok 4.3), say/do-gap tracking, pending commitments, constraint ledger, session openings (variety governor), failed approaches. The three BCT_HINTS delivery-style paragraphs (conformist / individualist / synthesist) are (A); everything per-user is (B).
→ hints absorb; state via /context
2.7 – 2.8BCT machinery · Routing manifests
A doctrine / engine-side
archetypes/bct_engine.py · intent_router.py + manifests/*.yaml
BCT selection conceptually belongs to the finetune; near-term its effect already reaches heavy Hermes through anchors + the [H3.0] gating hint — do not port it separately in v1. Routing scaffolds (203 KB) mostly aren't needed: Grok 4.3 with the grounding pack doesn't need a pre-classified skill id. Exception: /context still runs the router internally (cheap GPT-5.4-mini) so anchor retrieval gets skill-boost and Tier-3 inferences get filtered. Hermes never sees it.
2.9Post-generation guardrails
engine machinery · partly lost (§6.3)
_call_companion (api.py:4387)
_call_companion wraps every companion call with: roster unknown-name check, ledger-exclusion on deliverables, opener-variety governor, clinical-language literal + embedding checks, unsolicited-advice check on venting turns, content-recycling check — all folded into ≤1 bounded regeneration. These exist because a 12B model ignores prompt rules. Grok 4.3 needs them less, but "less" is unmeasured.
partially lost in heavy mode — see risk 6.3
2.10Vector memory — broken, known gap
B · needs fix
archetypes/vector_memory.py
Wants text-embedding-3-small but OLLAMA_URL points at OpenRouter, which 401s on embeddings. Meanwhile anchor_retrieval.py already runs local fastembed BGE-small (ONNX, ~5 ms). Remediation (independent of this project): port vector_memory to the same local pattern. Until then, semantic recall of past conversations is absent from every configuration.
Section 3

Heavy-Hermes architecture

Four constraints in hermes-agent 0.15.2 shape the design — and one of them is the escape hatch that makes it work.

3.1  Constraints discovered in the installed package

3.2  Data flow

Inbound
Telegram message
chat_id → user_id, per-sender JWT — same rules as today's SKILL.md.
Gateway
Hermes gateway
profile oimy-heavy · model x-ai/grok-4.3
Hook · fetch_grounding.sh
POST → 127.0.0.1:8090/context
include: [family, profile, anchors, ledger, honcho, topic], max_bytes: 16000 → returns labeled blocks; hook emits {"context": "<blocks>"}
Compose · natively
Grok 4.3 writes the reply
system = compiled SOUL.md  ·  tools = full Hermes toolset (reminders, calendar, web, media)
[FAMILY][PROFILE][HONCHO] [LEDGER][CURRENT TOPIC][COACHING ANCHORS ×3][ALREADY SAID]
Learning loop
Engine writeback
entity extraction · deep-profile store_message · h30 ledger/openings · Honcho append
↩ feeds the deep profile so heavy Hermes doesn't go stale
Outbound
Reply → Telegram

The engine's /chat remains untouched — light Hermes and the iOS/WhatsApp paths keep working. Heavy Hermes only adds two read/write endpoints beside it.

3.3  The /context endpoint (new, in api.py)

A thin HTTP wrapper over code that already exists — assembly order and caps copied from _call_companion's call sites.

POST /context — response
// Authorization: Bearer <per-sender JWT>  (body.user_id == JWT-subject)
→ 200 {
  "blocks": {
    "family":  "[FAMILY — people in this parent's household...]",   // ≤600
    "profile": "[User]...[Facts]...[Psych]...[Inferences]...[H3.0]...", // ≤2500
    "anchors": "[COACHING ANCHORS — deliver as your own insight] ###...", // ≤12288, 0–3
    "ledger":  "[CONSTRAINT LEDGER — HARD RULES]\n- no pork\n- budget $60/wk",
    "honcho":  "[HONCHO] ...",
    "topic":   "[CURRENT TOPIC] ..."
  },
  "anchors_delivered": ["becky-kennedy-good-inside"],   // deliver-once bookkeeping
  "meta": { "skill_hint": "parenting-coach", "router_confidence": 0.86 }
}

3.4  The compiled SOUL.md (soul.d/ + manifest)

Single-sourced in the engine repo, not in ~/.hermes. build_soul.py compiles the manifest into a per-target SOUL.md and enforces the 20 K cap; the profile file is a build artifact.

/opt/oimy-engine/hermes-heavy/soul.d/
00-identity.md          # Oi persona core + inner life          ~2.0K
05-safety.md            # crisis gate, medical boundaries       ~1.5K  absorb: never
08-grounding.md         # how to use [FAMILY]/[PROFILE]/[ANCHORS]  ~1.5K  absorb: never
10-voice.md             # distilled companion doctrine (combined_v2) ~8.0K
15-anti-sycophancy.md   # hard rules block, verbatim              ~1.2K
20-coaching-foundation.md # DISC/attachment delivery switching     ~1.5K
30-planning.md          # constraints stated>inferred>default     ~1.5K
40-telegram.md          # formatting, reactions, identity         ~1.2K  absorb: never
50-harness.md           # relationship modes 1-4, proactive, tools ~1.8K  absorb: never
                                                        ── total ≈ 18.2K < 20K ✅

Where a module distills a live engine prompt (10-voice from combined_v2), the header records source file + mtime, and build_soul.py --check warns when the source is newer than the distillation — a drift alarm (§6.2).

3.5  Sessions and memory: who owns what

🗣 Hermes owns conversational flow

short-term continuity
  • Its own session persistence (state.db, FTS-indexed, context_window: 20, overflow summarization) gives real multi-turn continuity — better than the engine's own history handling. Keep it.

🗄 Engine owns long-term memory

the family, forever
  • Entity graph, deep profile, H3.0, Honcho. Read via /context, fed via writeback. Hermes' own memories/ plugin stays disabled for family facts — two competing memories is how you get "didn't you say Emma was 7?"
Section 4

The swap mechanism: Grok 4.3 → finetuned Gemma 4

The finetune is not a generic model — it is trained on the 17-family / ~874-row gold-standard dataset whose entire purpose is mental-health depth, emotional-support quality, and multi-day handling. That specificity decides exactly what moves into weights and what must stay injected.

Genuinely absorbed → drop from context (post-ablation)

behavioral competencies move into weights
  • Voice, anti-sycophancy, attunement, pacing — every gold response embodies these, across crises and (thanks to the ≥50–60% ordinary-day floor) boring Tuesdays. Strongest absorption case in the system.
  • BCT-grounded, profile-conditioned delivery — "D-type gets the mechanism, S-type gets the feeling named first" becomes a trained reflex, not a prompt rule.
  • Multi-day continuity as a skill — 42-day arcs teach the model to use a supplied history window and profile block: reach-backs, ambient pattern-noticing, self-erasing restraint on ordinary days.
  • Ordinary-day uplift + cultural register (transliterated Hindi/Tamil/Telugu, 4 Indian families) — no SOUL module attempts these today; the finetune adds capability.

Never absorbed → inject at inference time, forever

the finetune expects these blocks present
  • Multi-day continuity's state — the dataset teaches what to do with a history window; it can't teach what happened in this family last Tuesday. Post-swap the model is out-of-distribution without [PROFILE]/[FAMILY] — memory gets more load-bearing, not less.
  • The context-block format is a train/serve contract/context blocks must be byte-compatible with the training renderer (assemble_contexts.py). Single-source them, or the Gemma swap underperforms for a reason no eval will localize.
  • History shape — production is user-turns-only; Hermes builds alternating user/assistant arrays. Fine for Grok 4.3, out-of-distribution for the finetune → a message-array adapter is required (§4 step 4).
  • Coaching-anchor breadth — 874 rows can't cover 35 frameworks × 4 DISC × attachment × failed-approach. Expect partial absorption: keep anchors at top_k=1, drop a framework only when per-framework ablation proves it.
  • Tool use, planner mechanics, Telegram, safety/crisis — the dataset has zero tool-call turns. These stay absorb: never.

Everything hinges on modules.yaml tagging and /context include-params. One manifest, two targets:

/opt/oimy-engine/hermes-heavy/modules.yaml
targets:
  grok-4.3:
    model: x-ai/grok-4.3
    context_include: [family, profile, anchors, ledger, honcho, topic]
  gemma4-ft:
    model: <fireworks-or-local slug>
    context_include: [family, profile, anchors, ledger, honcho, topic]
    anchors_top_k: 1              # partial absorption (§4.4)
    history_adapter: user-only    # match training shape — REQUIRED
    block_format: assemble_contexts   # must match the training renderer

modules:
  - id: 00-identity            absorb: finetune   # voice/persona → training data
  - id: 05-safety              absorb: never      # safety never rides on a finetune
  - id: 08-grounding           absorb: never      # runtime-data protocol is inference-time
  - id: 10-voice               absorb: finetune
  - id: 15-anti-sycophancy     absorb: finetune   # but see eval note
  - id: 20-coaching-foundation absorb: finetune
  - id: 30-planning            absorb: finetune
  - id: 40-telegram            absorb: never      # channel mechanics, model-agnostic
  - id: 50-harness             absorb: never      # harness behavior, model-agnostic

The flip, concretely

  1. build_soul.py --target gemma4-ft

    SOUL.md shrinks ~18 K → ~6 K (safety + grounding + telegram + harness only).

  2. Edit config.yaml

    model.default → the finetune slug.

  3. Hook reads new include/top_k

    The pre_llm_call hook reads include/anchors_top_k from the same manifest → the per-turn pack shrinks accordingly.

  4. Enable the history-shape adapter

    history_adapter: user-only so the message array matches the trained shape. The one step that is a correctness requirement, not a tuning knob — skipping it silently degrades the finetune.

  5. Nothing else changes

    /context, writeback, JWTs, sessions, Telegram all identical. Rollback = rerun with --target grok-4.3 (adapter off).

Why this is safe — and self-reinforcing

absorb: never modules and every category-(B) block are invariant across targets — a family's live roster, profile, inferences and ledger are always injected, any model, forever. absorb: finetune is a claim verified per module by ablation, not a promise (expect anti-sycophancy to need a residual 3-line reminder). And because heavy-Hermes transcripts are the finetune's training data, the loop closes: the better heavy Hermes runs, the better the finetune that replaces its static half.

Worked example · end-to-end

One emotional message, traced through the whole pack

A real family from loop-phase0 — the Reyes–Whitfield high-conflict co-parenting arc. Day 5. Danielle has spent four days rebuilding trust in systems over promises; here the wound reopens.

Inbound Telegram message
User Danielle Whitfield · user_id 8040940969 Profile High C · anxious-preoccupied · post-betrayal documenter Arc high-conflict custody
"Marcus just texted that he 'can't do' his weekend with Theo. Two days' notice. I had the whole thing set up. I don't even know why I keep expecting different."
1
Gateway profile: oimy-heavy · model: x-ai/grok-4.3
Message lands at the Hermes gateway. chat_id resolves to user_id 8040940969, per-sender JWT OIMY_JWT_TOKEN_8040940969 minted. Before the model is called, the pre_llm_call hook fetch_grounding.sh fires.
2
Hook fetch POST 127.0.0.1:8090/context
The hook posts the raw message and the include list. Internally, /context runs the GPT-5.4-mini router (skill_hint: emotional-support, confidence 0.88), calls h30.update_constraint_ledger(), then retrieves the top anchors with the emotional-support skill-boost applied.
// request body from fetch_grounding.sh
{ "user_id": "8040940969",
  "message": "Marcus just texted that he can't do...",
  "include": ["family","profile","anchors","ledger","honcho","topic"],
  "max_bytes": 16000 }
3
Block: [FAMILY] entity_context · ≤600 · never-invent-names
[FAMILY — people in Danielle's household & co-parenting orbit]
Danielle Whitfield — parent (primary user)
Theo — son, 8, asthma (rescue inhaler travels in his bag)
Marcus — ex-husband, co-parent (parenting-plan channel only)
Priya — Marcus's fiancée
// hard rule: never invent a name not in this block
4
Block: [PROFILE] _build_profile_context · ≤2500
The keys the anchor's delivery variants switch on — plus the day-2 failure the engine still remembers.
[Psych]  DISC: High C  |  attachment: anxious-preoccupied
        |  Hughes need: reliability / to-be-taken-seriously
[Inferences] (Opus, top-5)
  · trusts systems > promises since the betrayal (conf 0.82)
  · builds-a-case under threat; re-reads own texts 6–7× (0.79)
  · day-4: self-caught the loop, re-read once — regulation gain (0.71)
[H3.0]  engagement: high | domain: co-parenting | BCT gate: validate-first
[Failed Approaches]
  · day-2 "bridge-pending" defer (went quiet, made her chase) — DO NOT repeat
5
Block: [COACHING ANCHORS] top-3 · 12 KB cap · deliver-once
Retrieval returns one anchor over the 0.50 threshold (score 0.71), skill-boosted for emotional-support. Delivered as Oi's own insight — the framework name never appears in the reply.
### anchor: self-worth-not-contingent-on-their-reliability  (score 0.71)
CORE INSIGHT: the ache isn't "I keep hoping" — it's self-blame for
  having hoped. Separate his unreliability (his pattern) from her
  worth (not on trial here).
DELIVERY [High C + anxious-preoccupied]: name the competence she
  already showed; give her one concrete lever, not reassurance-spray.
IF PRIOR DIDN'T LAND: do NOT defer or "sit with it" (see Failed).
anchors_delivered: ["self-worth-not-contingent-on-their-reliability"]
6
Blocks: [LEDGER] · [HONCHO] · [CURRENT TOPIC]
[CONSTRAINT LEDGER — HARD RULES]
  - schedule changes go through the parenting-plan channel, not side-texts
  - Theo's rescue inhaler travels in his bag every handoff
[HONCHO] recurring dialectic: she reads logistics failures as
  evidence about her judgment, then over-documents to feel safe.
[CURRENT TOPIC] Marcus cancelled weekend, 2 days' notice; plans already set.
7
Assemble hook emits {"context": "<blocks>"}
The six labeled blocks (≈4.1 KB total, well under the 16 KB budget) are concatenated and returned to the gateway. Grok 4.3 now receives: system = the compiled SOUL.md (identity + safety + grounding protocol + distilled voice + coaching foundation + planning + telegram + harness, ≈18.2 KB) followed by the injected [FAMILY]…[ANCHORS]…[LEDGER] pack — plus Hermes' own last-20 session window and its full toolset.
8
Grok 4.3 composes natively no /chat call — Hermes writes it
The grounding protocol tells it: ledger = hard rules, anchor delivered as own insight, honor the "don't defer" failed-approach note, name the competence in [Inferences].
"Two days' notice, after you'd set the whole thing up — of course that lands hard. But notice what you just did: you named the pattern instead of building the case file. That's the version of you from Thursday, not the one who re-reads texts seven times.

His flaking is about his reliability, not your judgment for having planned well. Want to send the reschedule through the parenting-plan channel now — I'll draft it so it's short, documented, and closes the loop — and then figure out the actual weekend with Theo?" ✓ validated first · ✓ named the day-4 regulation win · ✓ separated his pattern from her worth · ✓ routed through the ledger's channel rule · ✓ answered synchronously — no day-2 "bridge-pending" defer · ✓ no framework name, no clinical language
9
Writeback POST /context/writeback · source: hermes-heavy
After the reply sends, the hook posts the completed exchange back. The engine runs entity extraction, deep_profile.store_message, the h30 ledger/openings update, and a Honcho append — and marks the anchor delivered so it won't repeat this session. The deep-profile pipeline (Opus) sees the turn, so tomorrow's [Inferences] stay current. Row tagged source="hermes-heavy" for later finetune export.
Section 5

What to build first (Grok 4.3 variant, buildable now)

Ordered. P0–P2 are the minimum honest test. Estimates assume familiarity with api.py.

P0 · Profile skeleton

≤ 1 h
  • hermes profiles create oimy-heavy — keep the per-sender JWT env pattern from oimy-dev verbatim.
  • config.yaml: model.default: x-ai/grok-4.3, keep fast: gpt-5.4-mini, tool_search on.
  • Restore SOUL from the backup as a stopgap; point at a separate (third) bot token so light- and heavy-Hermes run side by side against the same dev engine and same family data.

P1 · soul.d modules + compiler

~ half day
  • Create hermes-heavy/{modules.yaml, build_soul.py, soul.d/}. 00/15/40/50 are cut-and-organize from the SOUL backup; 20 is the anchors header; 30 a fresh ~40-line distillation of ConstraintFitScorer.
  • The real writing task is 10-voice: distill combined_v2 40 K → 8 K, keeping message-reading, emotions-first, venting, pacing, opener bans, memory-weaving, never-do list. (Fable drafts; needs Bharath's read.)
  • build_soul.py: concatenate per target, hard-fail over 19,500 chars, stamp header, --check for source-drift warnings.

P2 · Engine /context + writeback

~ 1 day · dev first
  • POST /context: plumbing around existing calls (get_context_summary, _build_profile_context, anchor_retrieval, h30 ledger, Honcho, topic). Reuse the JWT check from /chat.
  • POST /context/writeback: store both messages through the same post-response paths, mark anchors_delivered, tag rows source="hermes-heavy".
  • Smoke: curl /context for both user_ids; verify blocks match what a /chat turn logs today.

P3 · The hook

~ 2 h
  • fetch_grounding.sh: read hook-stdin JSON, resolve sender→user_id→JWT, POST /context, print {"context": ...}. Config: hooks: block with pre_llm_call, hooks_auto_accept: true.
  • Writeback via a post-response hook event if 0.15.2 exposes one (open item); else one-turn-lagged writeback from the same hook.
  • Retire the engine SKILL.md here — replace with a slim oimy-grounding one: "context arrives automatically; do NOT call /chat; you compose the reply."

P4 · Side-by-side eval

~ half day, then ongoing
  • Three arms: engine /chat, light Hermes, heavy Hermes. Score with the engine's existing checks (opener repetition, clinical leak, roster hallucination, ledger violations, venting protocol) run offline as judges.
  • Instrument the two defining failure modes: (a) grounding present but visibly ignored; (b) roster-name inventions. Threshold judgment: Bharath's.

P5 · Later / with the finetune

post-swap
  • Per-module ablation evals → flip absorb claims from "intended" to "verified."
  • Transcript export job (source="hermes-heavy", quality-filtered) → finetune training set.
  • Fix vector_memory (fastembed port) — benefits every configuration.
Explicitly not in scope: touching light Hermes (oimy-dev), the engine's /chat router/companion path, or prod (:8080) until dev has soaked.
Section 6 · honest

Open risks and questions

What could disappoint, and which calls are Bharath's product judgment rather than an engineering default.

6.1Does the hook mechanism fully work as documented?

The wire protocol documents pre_llm_call context injection and the config plumbing exists — but a live hook has not been executed under the Telegram gateway here. Verify first in P3 before building anything downstream. Fallback: a tiny local proxy in front of OpenRouter that injects the pack — uglier, model-agnostic, guaranteed.

6.2Drift between heavy Hermes and the engine's prompts

Anchors and all (B) data are single-sourced by construction. The genuine risk is 10-voice.md — a distillation, i.e. a second artifact. Mitigations: build_soul.py --check mtime alarm; the offline judge suite. Not fully solvable — a distillation is an editorial act. Decide deliberately who owns it.

6.3Loss of mechanical guardrails

Engine turns get post-generation enforcement; heavy-Hermes turns get prompt rules plus a stronger model. The engine measured 1.7–5.6% clinical leak at 12B; frontier should be far lower but is not zero. Option: add a validation pass in writeback that flags (not blocks) violations.

Bharath's product call

6.4Deliver-once bookkeeping across two composers

/context marks anchors delivered when served, but Grok may not use a served anchor — over-marking suppresses a framework never delivered. V1 accepts this (conservative is safe per "wrong anchor worse than none"). V2: writeback adds a cheap "anchor actually used?" judgment.

6.5Proactive-messaging ownership

Both layers can initiate — two initiators = double-texting the family. V1: disable engine-side proactive for heavy-profile users; Hermes owns rhythm, using /context for content.

Deliberate decision, not a default

6.6Cost / latency

Per turn: one GPT-5.4-mini router call + local retrieval, then one Grok 4.3 completion with ~16 K injected + ~18 K SOUL + tool schemas. Roughly comparable to today's engine path, slightly heavier on input tokens. Fine for a test rig; at scale the finetune swap is the answer by design.

6.7Multi-user provisioning stays manual

The per-sender JWT scheme is inherited as-is; any new family member needs a minted token + env var. Fine for the test cohort; a /provision flow is needed before any wider pilot.

6.8What is "heavy Hermes on Gemma-FT," exactly?

The finetune's training scope contains zero tool-call turns — it is a conversational companion, not a harness driver. Post-swap: either (a) Gemma-FT is the core and the fast: gpt-5.4-mini slot handles tool orchestration (a two-model harness), or (b) tool-heavy turns route away from Gemma-FT. The architecture supports both, but the choice changes what 50-harness says per target.

Founder call, with eval data

6.9The strategic question (pure product judgment)

Heavy Hermes makes the Hermes layer the product brain and demotes the engine to a knowledge service; the engine roadmap makes Hermes a dumb pipe. Both are now real, testable configs sharing one knowledge base — but they are competing theses about where OiMy's soul lives, and P4 only measures response quality, not strategy (on-device story, unit economics, moat). This document builds the comparison rig; it does not pick the winner.

Bharath's call, with data

Appendix · verified facts referenced above

  • Dev engine oimy-engine-dev.service, port 8090, COMPANION_MODEL=x-ai/grok-4.3, ROUTER_MODEL=openai/gpt-5.4-mini, FALLBACK_COMPANION_MODEL=anthropic/claude-haiku-4-5, DEEP_INFERENCE_MODEL=…/claude-opus-4.8. Prod identical minus PORT/prompt-file.
  • hermes-agent 0.15.2 (pipx), profile oimy-dev, current model.default: moonshotai/kimi-k2.6, tool_search threshold 5%, context_window: 20, state.db with FTS.
  • SOUL truncation CONTEXT_FILE_MAX_CHARS = 20_000prompt_builder.py:819. Hook injection {"context": ...}shell_hooks.py docstring.
  • Anchor caps ANCHOR_THRESHOLD=0.50, ANCHOR_TOP_K=3, ANCHOR_BYTE_CAP=12288, SKILL_BOOST=0.06, DELIVERED_DEMOTION=0.15anchor_retrieval.py.
  • Profile cap 2,500 chars — api.py:_build_profile_context (~4041). Entity cap 600 chars w/ never-invent-names — api.py:~4818.
  • Engine endpoints today: POST /chat, GET /profile/*, /verify/*, /gap/* — no /context yet.