Skip to content

Source Study

This page studies the local upstream hermes-agent source as an architecture donor for Gormes. It is not a request to port Hermes line-by-line. The goal is to keep the good contracts while avoiding the Python runtime coupling that made Hermes hard to shrink.

  • Upstream studied: /home/xel/git/sages-openclaw/workspace-mineru/hermes-agent
  • Upstream commit: ee1a07f9
  • Gormes repo studied: /home/xel/git/sages-openclaw/workspace-gormes/gormes-agent
  • Gormes commit: a8a62302
  • Date: 2026-04-27

The synchronized Hermes head is now ee1a07f9 Honcho remains e659b6b. The Gormes memory direction is unchanged: internal implementation stays goncho, while public compatibility surfaces keep honcho_* names and Honcho v3 data-shape expectations where hosts require them.

Material deltas in this window are already represented by focused rows:

  • Hermes ee1a07f9 blocks cross-provider reasoning-content leakage to DeepSeek/Kimi-family providers. Gormes already carries validated Phase 4.A reasoning-isolation and sanitization rows, so no new provider row is needed.
  • Hermes updated the Hindsight memory plugin and provider docs. Gormes keeps Goncho as the in-binary memory baseline and should not port a second memory provider until the Honcho-compatible Goncho surface is complete.
  • Gormes tracks the frontmatter validation contract as Phase 6.C SKILL.md frontmatter validation guard, not as a TypeScript CLI import.
  • Honcho e659b6b adds SillyTavern integration docs. Gormes already validated SillyTavern persona/group-chat mapping fixtures while preserving internal goncho naming.

Autoloop health changed the planning priority more than upstream did. The backend usage-limit/stdin health bypass is validated, so rows previously blocked only because worker attempts hit quota/stdin infrastructure were re-enabled as fixture-ready slices. Their health blocks remain preserved; the spec changes intentionally make those quarantines stale so the builder loop can clear them on the next selection.

The synchronized Hermes head is now 3ff3dfb5, moving beyond the prior b288934d study snapshot. Honcho remains at e659b6b. No new Honcho/Goncho memory naming behavior changed. Gormes should keep the internal goncho package direction and preserve public honcho_* tool contracts where compatibility requires them.

Material deltas in this window:

  • 3ff3dfb5 fixes Telegram group command-menu routing: Telegram emits /cmd@botname as one bot_command entity, not as a separate mention. Gormes has no group require-mention gate yet, so the roadmap adds Phase 2.B.5 Telegram group bot-command mention gate helper as a pure helper slice and Telegram group mention gate config binding as the dependent runtime/config slice.
  • 8258f4dc tightens custom-provider model switching so key_env-backed provider entries do not gain a synthesized api_key field during model changes. Gormes already has ResolveCustomProviderSecret; the roadmap now adds Phase 5.O Custom provider model-switch key_env write guard as a dependent write-shape helper before CLI/TUI /model binding.
  • af3d5150 hardens Matrix sender filtering against self-case mismatches, unresolved bot identity, and appservice/bridge puppet IDs, preventing the “hall of mirrors” pairing/echo loop. Matrix is still deferred in Gormes, so the roadmap adds Phase 7.C Matrix self/bridge sender drop helper, blocked behind the Matrix shared-chassis seam.
  • 8c5d3a99, 55be5323, and 7d586ddb add and clarify the creative design skill trio: claude-design, popular-web-designs, and design-md, with short descriptions and explicit routing guidance. Gormes should preserve the metadata/routing semantics before broadening portable SKILL.md storage, so Phase 6.C now includes Hermes creative skill metadata compatibility.
  • a131c134 only updates release author mapping and does not change the Gormes architecture plan.

The synchronized Hermes head is now b288934d, moving beyond the prior cb51baec study snapshot. Honcho remains at e659b6b. No new Honcho/Goncho memory naming behavior changed. Gormes should keep the internal goncho package direction and preserve public honcho_* tool contracts where compatibility requires them.

Material deltas in this window:

  • 91512b82 and 6993e566 harden gateway/whatsapp_identity.py by rejecting path-like and non-ASCII identifiers before alias expansion. Gormes does not port Hermes’ filesystem lid-mapping-* files, but the same invariant belongs in the Go WhatsApp alias graph. The roadmap now adds Phase 2.B.4 WhatsApp ASCII identifier guard.
  • e19854d8 fixes agent/shell_hooks.py so hooks_auto_accept: "false" no longer bypasses consent through truthy string coercion. Gormes hook loading is Go-native; the roadmap now adds Phase 5.J Gateway hook auto-accept strict parser before any auto-accept config wiring.
  • 16e243e0 and 366351b9 make Hermes provider timeout helpers fail closed when config loading raises. Gormes has not exposed provider request/stale timeout config yet, so this remains a provider-config hardening lesson instead of an executable row in this pass.
  • b288934d coerces Discord tool limit arguments to int before clamping. Gormes’ Discord tools are still descriptor-only, so the roadmap adds Phase 5.A Discord tool limit coercion helper before any Discord REST handler.

The synchronized Hermes head was cb51baec, moving beyond the prior b16f9d43 study snapshot. Honcho remains at e659b6b; no new Honcho/Goncho naming change is required. Gormes should keep the internal goncho package direction and preserve public honcho_* tool contracts where compatibility requires them.

Material deltas in this window:

  • 930494d6 fixes leaked MCP stdio subprocesses after cancelled cron ticks by tracking orphan stdio PIDs and sweeping only orphaned children after tick futures join. Gormes now tracks this as Phase 5.G MCP stdio orphan cleanup after cron ticks.
  • 7317d69f treats quoted false-like values as false in browser SSRF guard config. Gormes already has a pure private-URL route helper, so the roadmap now adds Phase 5.C Browser SSRF quoted-false guard before browser provider bridges become executable.
  • 635253b9 extends busy input behavior with steer. Gormes already had a steering row, but this run refined it with exact source refs, fixture names, and a narrower write scope for registry/fallback behavior before any kernel mid-run injection hook.
  • e85b7525, 478444c2, a32b325d, 977d5f56, ced8f44c, cebf9585, and dbe50155 are already represented by the current roadmap rows for ContextEngine boundary notification, checkpoint GC, file-read dedup guards, gateway message deduplication, and session_search lineage exclusion.
  • c997183f through 7e3c8a31 are already represented by the bundled Airtable skill contract row.

Additional Slack/session/update deltas (e818ec52, 8fb861ea, a01e767b, 7eaad06a, 55f212a7, 3b60abb6, fd474d0f, bdaf56a9, 90c84c6d) are real but were not expanded into more executable rows in this pass because the latest autoloop productivity signal favors reducing ambiguity in already-hot subphases. They should be split in a follow-up planner run as Slack attachment hardening, Slack channel-skill bindings/config transport guards, session file cleanup on delete/prune, per-user group mirror isolation, and update-prompt slash-bypass rows.

2026-04-27 (Telegram fresh-final streaming) Drift Check

Section titled “2026-04-27 (Telegram fresh-final streaming) Drift Check”

The synchronized Hermes head moved from 755a2804 to b16f9d43. Honcho is still at e659b6b; no new memory-provider or Honcho/Goncho compatibility behavior changed. Gormes should therefore keep the internal goncho package direction while preserving honcho_* public tool names where the external contract requires them.

The Hermes delta is narrow but user-visible for gateway streaming:

  • gateway/stream_consumer.py now tracks when the editable preview message was first created. On finalization, if fresh_final_after_seconds > 0 and the preview age meets the threshold, Hermes sends the final response as a fresh message instead of editing the stale preview.
  • gateway/platforms/base.py adds an optional delete_message hook, and gateway/platforms/telegram.py implements it through Telegram’s deleteMessage API so the stale preview can be cleaned up best-effort after a successful fresh final send.
  • gateway/config.py and website/docs/user-guide/configuration.md expose streaming.fresh_final_after_seconds with a 60 second default and 0 as the disable switch. gateway/run.py enables the setting only for Telegram.

Gormes already has internal/gateway/coalesce.go, gateway.MessageEditor, gateway.FinalizingMessageEditor, and internal/channels/telegram.EditMessage, but it has no preview-age threshold, fresh-final fallback, or Telegram delete seam. The roadmap now tracks this under Phase 2.B.5 as three worker-sized rows: Gateway fresh-final eligibility helper, Gateway fresh-final send/delete fallback, then Telegram fresh-final delete and config exposure.

2026-04-26 (auto-title, skills cleanup, Docker docs) Drift Check

Section titled “2026-04-26 (auto-title, skills cleanup, Docker docs) Drift Check”

The synchronized Hermes head moved from 0824ba6a to 9be83728; the sibling repo is now at 755a2804 after release-author mapping. Honcho remains at e659b6b; no new Goncho/Honcho memory row is needed from this Hermes delta. Internal implementation remains Goncho; public memory tools keep Honcho-compatible honcho_* names where external contracts require them.

The new Hermes delta is small but touches three planning surfaces:

  • 9662e321 wires maybe_auto_title() into tui_gateway/server.py after a clean prompt.submit completion with non-empty user prompt and assistant response. Gormes does not have the Python TUI gateway/session-key path, so the roadmap now tracks a native Phase 5.Q helper row, TUI prompt-submit auto-title eligibility helper, before any title generation or session metadata write is wired.
  • 93977675 removes the empty skills/feeds category marker and its website CATEGORY_LABELS["feeds"] entry. Gormes’ internal/skills surface does not have a static feeds category label, so this is documented in the Phase 5.F drift state rather than adding an executable row.
  • 9be83728 clarifies Docker terminal-backend lifecycle: the top-level agent reuses one default container across sessions, /new, and /reset, while delegate_task subagents and RL rollouts isolate by generated task_id. Gormes’ Phase 5.B Docker backend is still planned, so the roadmap now adds Docker backend top-level container reuse semantics as a pure keying row before live container execution.

The synchronized Hermes head moved from 42c076d3 to 0824ba6a. Honcho remains at e659b6b; no new memory-donor behavior changed, so the internal implementation name stays Goncho while public tool contracts keep honcho_* where compatibility requires it.

The Hermes delta is narrow but user-visible:

  • 0824ba6a updates /branch so an active agent’s session_log_file is redirected to the newly created branch session. Gormes has no Python session_log_file, but the equivalent native contract is that /branch switches the active TUI/kernel session ID and all later transcript writes use the branch ID, not the parent.
  • The same commit changes SessionDB.list_sessions_rich() so branch children are visible in default session lists while delegate subagents and compression continuations stay hidden. Gormes already has session.LineageKindFork and ResolveLineageTip ignores fork children; the missing slice is the native TUI /branch handler plus transcript-copy helper that writes fork metadata.
  • scripts/release.py only added an author-map entry and does not affect the Gormes architecture plan.

The roadmap now tracks this under Phase 5.Q as Native TUI /branch session fork + transcript target switch, blocked behind the existing native slash-command dispatch table and the validated session lineage contract.

The synchronized Hermes head moved from b2d3308f to eaa7e2db (25 new commits). Honcho and Gormes-owned were unchanged in this sync. The drift is mostly small CLI/gateway polish but a few items deserve roadmap rows in a future planner cycle:

  • eaa7e2db surfaces /queue, /bg, /steer in the agent-running placeholder. Gormes already tracks placeholder behavior under Phase 5.Q “TUI running-agent placeholder surfaces interrupt + queued slash actions”; the row should grow an explicit fixture per slash action.
  • de243159 and its fixup 4e356098 preserve the inactivity clock across interrupt-recursive cached-agent turns. Gormes’ Phase 2.F.3 covers session expiry finalization but not inactivity-tick preservation across nested interrupts. Worth a small follow-up row.
  • d7a34682 and 20cb706e rename [SYSTEM: to [IMPORTANT: in operator prompts so Azure content filters stop tripping. A small fixture row under Phase 3.E.* would guard the prefix invariant against drift.
  • f2d65552, 27f4dba5, 8443998d resolve API keys from ~/.hermes/.env before falling back to a credential pool. Gormes auth lives in internal/auth; the equivalent contract needs an env-fallback row that doesn’t assume a Hermes config layout.
  • 35c57cc4 suppresses tool-progress bubbles after an interrupt. Gormes’ newly split Phase 5.Q tool-summary formatter row should grow one synthesized interrupt-suppression case.
  • 7fa70b6c aliases /btw to /background and 70f56e76 lets /btw dispatch mid-turn. Phase 5.O should pick up the alias contract after the /reasoning row lands.
  • 1e37ddc9 adds a hermes fallback CLI command. Gormes already has fallback policy under provider routing but no operator-facing CLI; warrants a future Phase 5.O row, low priority.
  • 63bf7a29 prevents reasoning_content regression in DeepSeek/Kimi tool-call replay; reinforces the existing Phase 4.A fixture rather than needing a new row.

For the autoloop the immediate priority is to keep hot rows split and metadata-ready; that planner pass found no active quarantine blocks in progress.json, but recent failure categories still point to over-broad contracts and status-field mistakes. Nothing on this drift list is load-bearing for the next several builder cycles, so the new rows above stay deferred until quarantine clears.

The synchronized Hermes head is now b2d3308f after the local upstream moved from dc4d92f1 to b2d3308f. The new drift is narrow but execution-relevant:

  • ad0ac894 widens DeepSeek/Kimi/Moonshot replay padding from assistant tool-call turns to all assistant messages. Gormes already landed tool-call padding and cross-provider reasoning isolation, but its current internal/llm/http_client.go fixtures still leave plain assistant turns unpadded. The roadmap now tracks this as a small Phase 4.A provider row.
  • 25ba6a4a makes gateway /reasoning <level> session-scoped by default, keeps --global as the persistence opt-in, and clears model plus reasoning session overrides on /new/reset flows. Gormes has per-turn model override plumbing but no typed reasoning-effort request field or gateway command state yet, so the plan splits this into a Phase 4.D request-propagation row followed by a Phase 5.O gateway command row.
  • b2d3308f teaches Hermes doctor to accept bare custom provider configuration as valid operator intent instead of requiring a provider registry match. Gormes uses a different TOML/XDG config shape, so the plan captures the equivalent custom-endpoint readiness contract under Phase 5.O rather than porting Hermes config parsing.

Honcho and Gormes-owned were unchanged in this sync. The internal memory direction therefore remains Goncho as the Go implementation name, with Honcho-compatible public tool names and data shapes preserved where external contracts require honcho_*.

The synchronized Hermes head is now f93d4624. New drift since the earlier provider/compression notes is concentrated in the TUI, CLI startup, and provider replay surface:

  • 283c8fd6 and its child commits move model/provider overrides into TUI launch, resolve short model aliases statically, and avoid provider catalog network lookup during startup.
  • edc78e25, 31d7f195, bd66e55a, and 1735ced9 harden the Node/Ink TUI selection-copy path: SSH shortcut handling, rendered spaces, code-block indentation, and bounds clamping.
  • f93d4624 reorders _copy_reasoning_content_for_api so DeepSeek/Kimi replay of assistant tool-call turns injects an empty reasoning_content placeholder before promoting generic stored reasoning. That prevents reasoning emitted by one provider from leaking into another provider’s continuation request.

Gormes should not import Hermes’ Node/Ink runtime. The planner split the drift into native Go rows under Phase 5.Q: one for TUI model override/static alias startup, one for native selection/copy parity-or-divergence, and the existing no-Node bundle independence row. The provider replay drift is tracked as a small Phase 4.A row against internal/llm/http_client.go and internal/llm/reasoning_content_echo_test.go.

Hermes is a feature-rich Python agent runtime with many entry points feeding one large orchestration class:

CLI, TUI, gateway, cron, ACP, batch, API server
|
v
session, command, provider, and config resolution
|
v
AIAgent in run_agent.py
|
+--> prompt assembly and context compression
+--> provider transport selection
+--> tool schema selection and dispatch
+--> memory providers and plugin hooks
+--> session persistence and trajectory logs
|
v
provider APIs, tools, gateway delivery, SQLite state, files

The important lesson is not “copy AIAgent.” The lesson is that Hermes had to solve real integration contracts: provider-neutral tool continuations, stable prompt prefixes, gateway active-turn control, dynamic tools, persistent memory, and operator command parity. Gormes should keep those contracts in smaller Go packages owned by the kernel, gateway, tools, memory, and provider layers.

Core upstream evidence files at study time:

  • run_agent.py - AIAgent, provider routing, prompt use, tool loop, fallback, interrupts, memory hooks, and persistence; 12,662 lines.
  • cli.py - legacy interactive terminal experience; 11,116 lines.
  • gateway/run.py - GatewayRunner, session routing, slash commands, platform adapters, cached agents, progress delivery, active-turn control; 11,147 lines.
  • hermes_cli/main.py - top-level hermes command implementation and setup flows; 9,272 lines.
  • hermes_cli/commands.py - central slash command registry feeding CLI, gateway help, Telegram menus, Discord commands, and Slack mappings.
  • hermes_cli/runtime_provider.py and hermes_cli/auth.py - provider, credential, base URL, API mode, and custom endpoint resolution.
  • agent/prompt_builder.py - system prompt layers, skills prompt cache, context-file discovery, tool-use guidance, and injection scanning.
  • agent/context_engine.py and agent/context_compressor.py - pluggable context engine contract plus the default summarizing compressor.
  • agent/memory_provider.py and agent/memory_manager.py - built-in memory plus one external provider with prompt blocks, prefetch, sync, tools, and lifecycle hooks.
  • model_tools.py and tools/registry.py - self-registering tool modules, toolset filtering, availability checks, schema adjustments, plugin hooks, async bridging, and dispatch.
  • tools/delegate_tool.py - subagent launch, progress relay, depth limits, child credentials, and timeout diagnostics.
  • plugins/, skills/, and optional-skills/ - extension and procedural knowledge surfaces.
  • tests/ - 741 test*.py files across agent, gateway, CLI, tools, cron, plugins, memory, ACP, provider, and session storage behavior.

Gormes already has smaller equivalents for several contracts:

  • internal/llm/client.go owns the provider-neutral stream, tool-call, and tool-result event contract.
  • internal/kernel/kernel.go owns a single-goroutine turn loop and tool continuation loop.
  • internal/tools/tool.go owns compiled Go tool descriptors and execution.
  • internal/gateway/commands.go owns a small shared command registry.
  • internal/goncho/types.go owns Honcho-compatible search/context shapes.

AIAgent does too much, but the lifecycle it encodes is valuable:

sanitize user input
-> restore primary runtime after fallback
-> append user turn
-> reuse or build stable system prompt
-> preflight context compression
-> inject ephemeral memory/plugin context into the user message
-> make provider call
-> parse text, reasoning, and tool calls
-> execute tools sequentially or concurrently
-> append tool results
-> loop until final response, interrupt, fallback, or budget exhaustion
-> persist session and memory side effects

The strongest design move is prompt stability. Hermes caches the system prompt and injects volatile memory or plugin context into the current user message instead of mutating the system prompt every turn. That preserves prompt-cache prefixes and keeps plugin context out of stored system prompts.

The riskiest move is class gravity. AIAgent owns provider quirks, fallback, memory, tools, compression, prompt assembly, session persistence, callbacks, child agents, stream parsing, retries, and shutdown cleanup. Gormes should keep the same lifecycle but distribute ownership across typed packages.

Hermes supports several API modes:

  • chat_completions for OpenAI-compatible endpoints.
  • codex_responses for OpenAI Responses/Codex-shaped providers.
  • anthropic_messages for native Anthropic-compatible message APIs.
  • bedrock_converse for AWS Bedrock.

Runtime resolution is shared across CLI, gateway, cron, ACP, and auxiliary tasks. It inspects explicit args, saved config, credential pools, custom provider definitions, base URL hostnames, and provider-specific OAuth stores.

The good contract for Gormes is a provider-neutral stream/event shape plus adapter-specific request builders and response decoders. The bad pattern to avoid is letting provider-specific exceptions sprawl through the main kernel.

Hermes tools are dynamic:

tools/*.py self-register at import time
|
v
tools.registry.ToolRegistry
|
v
model_tools.get_tool_definitions()
|
+--> toolset filtering
+--> availability checks
+--> dynamic schema patches
+--> schema sanitization
|
v
AIAgent tool execution and result append

Some tools are intercepted before registry dispatch because they need agent state: todo, memory, session_search, delegate_task, clarify, and external memory-provider tools. Hermes also runs independent tool batches concurrently when safe and preserves tool-result order for the provider.

Gormes should keep explicit compiled tools as the default. It should borrow the descriptor richness: availability, toolset membership, result budget, prompt-visible safety, dynamic schema generation, and audit fields.

GatewayRunner is the most important upstream source for Gormes gateway work. It normalizes inbound MessageEvent values, checks authorization and pairing, dispatches slash commands, manages active sessions, queues or interrupts running agents, wires progress callbacks, streams partial replies, and caches AIAgent instances per session to preserve stable prompts.

Good mechanics to keep:

  • a unified event shape per platform;
  • explicit active-turn behavior for /stop, /queue, /steer, approvals, status, restart, background tasks, and ordinary follow-up text;
  • progress callbacks that do not block the agent loop;
  • session keys stable across platform/chat/thread boundaries;
  • cached session runtime only when the effective configuration signature matches.

Recent gateway sync delta (2026-04-24): upstream commit f731c2c2 tightened BlueBubbles/iMessage behavior. gateway/platforms/bluebubbles.py now treats BlueBubbles as non-editable, splits blank-line paragraphs into separate iMessage bubbles, and removes pagination suffixes from long-message chunks. gateway/session.py also adds a platform note that asks the model for short, conversational, blank-line-separated replies. Gormes should keep this as capability-based gateway behavior plus a BlueBubbles formatter fixture, not a special-case branch in the kernel.

Recent upstream sync delta (2026-04-25): upstream commit b35d692f adds five planner-relevant contracts:

  • auxiliary LLM calls retry once without temperature when a provider rejects that parameter, while Codex Responses keeps the no-temperature transport rule independent of the now-deleted memory-flush path;
  • cron jobs gained context_from so one scheduled job can inject bounded output from previous jobs without blocking on same-tick runs;
  • Discord session sources now preserve guild_id, parent_chat_id, and message_id for tool/action context;
  • Discord tools split into least-privilege discord and discord_admin toolsets, and hermes tools persistence now hardens MCP names, numeric keys, no_mcp, and platform-scoped toolsets;
  • root Linux install.sh behavior now has an FHS-style layout decision that Gormes must either port or explicitly diverge from in tests and public docs.

Gormes tracks these as small rows: 4.H unsupported-temperature retry, 5.N context_from, 2.B.11 Discord source metadata, 5.A/5.O toolset rows, and 5.P installer policy.

Latest upstream sync delta (2026-04-25): commits 6e561ffa, 97d54f0e, af22421e, cf2fabc4, d635e2df, 7c17accb, 648b8991, and ee0728c6 add planner-relevant contracts tracked in progress.json:

  • update/service restart verification now polls active status instead of doing a one-shot sleep check;
  • terminal process watch-pattern notifications now need throttling, post-exit suppression, and notify-on-complete promotion;
  • dashboard page-scoped plugin slots should be preserved as metadata/API contracts without importing the upstream React runtime;
  • auxiliary compression feasibility must pass provider identity into context length resolution so Codex uses the provider cap before headroom math;
  • stream retries must check cancellation before opening a fresh connection, so /stop cannot be negated by a retry loop;
  • Codex Responses assistant replay messages must serialize text parts as output_text, while user messages keep input_text;
  • Hermes TUI first-launch rebuild checks now treat a missing packages/hermes-ink/dist/ink-bundle.js as stale even when dist/entry.js exists, which Gormes tracks as an explicit native-TUI/no-Node divergence row rather than a Node/Ink build port.

Gormes tracks these as small rows in 5.O service restart polling, 5.A terminal notification throttling, 5.I dashboard slot inventory, and 4.B provider-aware auxiliary compression, with a new 5.Q native TUI bundle-independence fixture for the ee0728c6 drift. The 4.B provider-cap slice is complete on main; the remaining rows stay fixture-first until their local substrates exist.

Previous context sync delta (2026-04-25): upstream commit 5401a008 changed agent/context_compressor.py so ContextCompressor.update_model() recalculates threshold, tail, and max-summary token budgets when the active model window changes. Gormes has already mirrored the pure budget behavior in internal/llm/context_compressor_budget_test.go; remaining work is kernel model-override wiring and real history pruning/summary feedback, not another metadata-only row.

Risk to avoid: the running-agent command path is a long imperative chain inside one very large file. Gormes should put active-turn policy in the command registry itself, then let adapters and gateway.Manager consume that policy.

Hermes has two extension points that Gormes should preserve in Go:

  • ContextEngine: one active compaction engine decides when and how to compact message history and may expose context-specific tools.
  • MemoryProvider: built-in memory is always active, and at most one external provider runs beside it. Providers can add prompt text, prefetch recall, sync completed turns, expose tools, observe compression, and observe delegation.

The best pattern is lifecycle clarity. The dangerous pattern is prompt/tool surface growth. Every active provider can add prompt blocks and model-visible tools, so Gormes should gate provider tools, budget prefetch latency, and make degraded memory state visible in gormes memory status and gormes doctor.

Hermes has meaningful tests around architectural edge cases: session storage, tool-call serialization, reasoning preservation, CJK search fallback, gateway command safety, fallback providers, plugin loading, context compression, tool schema filtering, cron, ACP, and provider adapters.

The Gormes lesson is to keep writing architecture tests, not just unit tests:

  • provider transcript fixtures for each adapter;
  • tool schema parity fixtures against upstream;
  • active-turn gateway policy fixtures;
  • prompt assembly snapshots;
  • memory scope negative tests;
  • plugin/skill resolver conformance;
  • context compression replay fixtures.

Hermes is the upstream capability ledger. Gormes should port:

  • provider-neutral event contracts;
  • gateway command/session semantics;
  • prompt assembly rules;
  • tool descriptor metadata;
  • memory/context provider lifecycle;
  • skill and plugin operator surfaces;
  • tests for edge behavior.

Gormes should not port:

  • the giant Python class layout;
  • import-time tool registration as the core model;
  • provider quirks inside the kernel;
  • gateway command behavior as a long if/elif chain;
  • silent fallback and degraded modes;
  • arbitrary plugin code inside the trusted runtime by default.