ADR-046 β Message-only Humanwork boundary; Hermes owns the turn
Status: Accepted (2026-08-05)
Date: 2026-08-05
Implementation remediation ledger: ADR-046 confirmed violations to remove
Supersedes in part: ADR-045, specifically its MCP-only external-action rule, completion/content/review gates, mandatory approval bridges, and any description of Humanwork-built per-turn context.
Retires as current architecture: the deleted
agent-runtime-v2-implementation-contract.md and
agent-runtime-v2-feature-parity-matrix.md. Git history remains the record of
the migration; retired instructions do not remain in the live documentation
tree.
Contextβ
The managed Hermes/AgentFS/SessionDB runtime was already capable of fast, persistent turns. Later control-plane and compatibility work accumulated around it and changed the effective product:
- Humanwork retrieved KB snippets before every turn and injected them into the message instead of letting Hermes retrieve knowledge when needed;
- dead or duplicated prompt assemblers still performed work even when their output was not the managed Hermes prompt;
- wrappers, capability notices, attachment prose, response-style blocks, directives, source/citation mandates, and correction examples decorated the user's message;
- task classification narrowed tools per turn, while ACP permission callbacks added a blocking round trip even when Humanwork automatically approved it;
- native browser, network, image, filesystem, and shell capabilities were incorrectly treated as actions that must be replaced by MCP;
- reply policies marked successful low-risk replies
held_for_review, and synthetic delivery envelopes/projections created more than one transcript representation; - host homes, prompt/session caches, machine-side seeding, and one-shot hydrate/flush helpers duplicated state already owned by AgentFS, SessionDB, and the resident session machine;
- the Hermes supervisor path replaced
Bun.spawnwith a native exec helper to avoid a procfs pathname even though that was not a functional requirement; - documentation preserved these transitional mechanisms as if they were the desired architecture.
The result was larger model requests, avoidable pre-model latency, tool loops, delivery holds, duplicate state, and an architecture that made Humanwork a second agent rather than a transport and control plane.
Decisionβ
1. The model turn is the inbound messageβ
Humanwork sends Hermes the exact inbound message as native ACP content blocks. It does not prepend, append, wrap, summarize, classify, ground, flatten, or otherwise rewrite those blocks. A text message remains a text block; an attachment is its own real message and remains a standard ACP resource, image, audio, or embedded-resource block. A caption, when present as a distinct inbound text message, remains a distinct text block/message.
If the inbound message includes real binary attachments, the API writes the
bytes directly to the conversation namespace in the organization's cloud
AgentFS before dispatch. The standard ACP resource block references that
AgentFS-visible object; Humanwork does not copy
the bytes into R2/base64, invent a descriptor/envelope, or attach the file to a
different text row. Native Hermes ACP resolves and processes the block through
its existing virtual /workspace filesystem behavior.
hermes-run and its supervisor expose Hermes ACP unchanged. They authenticate,
supervise, and relay raw ACP bytes; they do not parse content blocks or replace
Hermes' native ACP behavior with a Humanwork-specific protocol.
Hermes ACP is not a patch surface. No maintained bake-time patch may touch
acp_adapter/, agent/turn_context.py, run_agent.py, the hermes-acp
toolset, or otherwise alter native content blocks, session methods,
permissions, updates, tool events, results, or errors. If an upstream ACP bug
must be fixed, Humanwork advances to an upstream Hermes revision containing the
fix; it does not carry a private ACP fork.
The following are forbidden in a per-turn model message:
- KB snippets or a
kbContextProvidedmarker; <user_message>,<current_expert_request>, or similar trust wrappers;<granted_tool_capabilities>, synthetic attachment notices, or capability summaries;- active-directive, response-style, crisis, task-state, or tool-grant blocks;
- source/citation, live-tools-first, web-research, or forced-tool-use text;
- correction few-shots, synthetic history, or an assembled-prompt body;
- fabricated system, assistant, user, or delivery messages.
This is a block-and-byte-level boundary, not a convention. Tests must compare the native ACP content blocks sent through the supervisor with the actual inbound messages accepted at the API boundary.
2. Hermes owns everything agenticβ
Hermes owns:
- its system prompt and stable persona;
- its retained conversation history in SessionDB;
- configured skills and their on-demand loading;
- tool discovery and progressive disclosure;
- deciding whether KB, web, browser, image, file, shell, or another capability is needed;
- invoking those tools and incorporating their results;
- deciding whether and how to cite sources;
- clarification and response style.
Humanwork transports, authenticates, persists, observes, and delivers. It does not perform these responsibilities before Hermes sees the message.
Organization defaults are established once in the organization's AgentFS. Conversation-specific persona, environment, and configured session assets are established once when a new Hermes session is created. They are not re-rendered or re-sent on later turns.
3. Native tools first; MCP only fills a missing capabilityβ
This rule is platform-wide, not Hermes-specific:
- use a normal/native tool when that capability exists;
- use MCP only when the capability is not available as a normal tool.
Git CLI, shell, filesystem, Chromium/browser, direct web/network tools, native image generation, and configured provider tools remain normal capabilities. Humanwork must not remove or shadow them merely because an MCP alternative exists.
The primary Git capability is HyperSH Git, the normal git CLI implemented
at runners/hermes-binary/worker/hypersh-git. The AgentFS worker registers its
gitCommand as a just-bash custom command, so Hermes reaches it through the
ordinary native terminal tool and all repository reads and writes target the
session workspace in AgentFS. It is available without prompt advertisement, a
Humanwork grant, or MCP.
HyperSH Git is the agent's first choice for repository work. An authenticated
normal git or gh command is likewise preferred when it supplies a required
forge operation. A GitHub/forge MCP tool is a fallback only for a
hosting-account capability unavailable through those normal tools; it does not
replace or shadow HyperSH Git.
MCP is additive. It supplies organization capabilities such as Humanwork KB or connected services that have no equivalent normal tool. MCP routing retains tenant authentication and credential selection, but no Humanwork review, task-classification, read-ceiling, content-policy gate, approval carrier, or continuation may block or reshape the call.
Hermes owns tool-schema presentation, including any progressive disclosure
the pinned runtime natively supports. Humanwork must not add a discovery
bridge, replace a native schema with tool_search/tool_describe/tool_call,
inject a textual tool catalog into the prompt, or send a per-turn task-narrowed
grant list. If Hermes directly offers a configured native, plugin, or MCP
schema, Humanwork passes that behavior through unchanged.
Pinned upstream Hermes may issue native ACP session/request_permission for a
dangerous command or edit. The supervisor relays that interaction unchanged;
the noninteractive Humanwork ACP client selects the offered allow_once
option for the current invocation. Humanwork must not persist the selection,
turn it into a review queue, or replace the native request with a private
Hermes patch.
Hermes' intrinsic tool semantics, including its own catastrophic-command protection, remain Hermes-owned. This ADR removes Humanwork review ceremony around those tools; it does not require Humanwork to fork tool safety logic into another layer.
4. There are no Humanwork delivery gatesβ
A successful Hermes reply is delivered exactly once. Delivery does not depend on confidence, risk, red-line classification, reasoning-leak classification, clarification/card parsing, a request for a human, review state, evidence use, tool use, completion checks, or an approval continuation.
Expert review may observe or correct a delivered reply after the fact. It is never a prerequisite for delivery.
An actual agent failure has no reply to deliver. Humanwork records and returns the failure; it must not manufacture fallback prose, a canned acknowledgement, a clarification card, or a queue substitute and present it as the agent.
held_for_review, reply-level waiting_approval, compatibility-bypass flags,
and similar legacy state must not participate in reply delivery or ordinary
tool availability. The opt-in write-action carrier may retain its own action
state, but that state is not projected into the Hermes transcript and cannot
hold unrelated output. Obsolete paths and flags are deleted rather than
retained dark for later reactivation.
Amendment (2026-08-06, product decision, #5673): the clarifying-card directive parse at the wrapper is restored as a sanctioned exception to Β§2 ("clarification β¦ " stays Hermes-owned) and to this section's "clarification/card parsing" clause. The managed wrapper lifts one model-authored
<<<HW_QUESTION β¦>>>block out of the reply so the raw directive never reaches a client, and persists the structured card as a locator-keyed Postgres governance row. This is transport, not a gate: the reply still delivers exactly once and unconditionally, a malformed directive degrades to prose, and Humanwork still never manufactures a card the model did not emit. SessionDB remains the sole prose authority β the canonical transcript keeps the reply verbatim, and the client-view serializer performs the same lift at read time.
5. AgentFS and SessionDB are the only session authoritiesβ
Each organization owns exactly one cloud AgentFS database and exactly one
separate cloud SessionDB database. AgentFS is the authority for every file
owned by that organization's managed agent. SessionDB is the authority for all
native Hermes sessions and transcripts in that organization. A native
session_id separates conversations inside the shared SessionDB; Humanwork
retains only the exact conversationId -> session_id routing association.
Postgres may store routing, governance, audit, and exact transcript locators;
it is not a second prose or file authority.
The organization AgentFS has this canonical hierarchy:
/
βββ .env # private organization-wide environment
βββ SOUL.md # private organization-wide persona defaults
βββ config.yaml # private organization-wide Hermes defaults
βββ memory/ # one shared durable organization memory
βββ skills/ # shared configured skills
βββ conversations/
βββ <conversationId>/
βββ .env # private credential/environment issued for this conversation
βββ SOUL.md # private effective conversation persona
βββ config.yaml # private effective conversation configuration
βββ state/ # private conversation runtime state
βββ work/ # durable normal-tool workspace
βββ artifacts/ # inbound and generated file objects; no turn staging
βββ logs/ # native conversation logs
The two .env/SOUL.md/config.yaml levels are intentional. The organization
level is the shared base. The conversation level is the stable effective
configuration issued when that Hermes conversation is created. A warm turn
does not rebuild either layer. Hermes reads its conversation-private home via
the AgentFS interpose boundary. Normal filesystem and shell tools are rooted at
the authorized conversation workspace and cannot list, read, or traverse to
the conversation-private files or the organization root. Credentials never
enter ACP, model content, client responses, logs, or transcript prose.
memory/ is organization-wide and shared by the organization's Hermes
sessions. Conversation state and files remain separated beneath
conversations/<conversationId>/; there is no per-conversation AgentFS
database and no per-conversation SessionDB database.
The process and filesystem composition is:
Zig supervisor
-> confined exec of one resident Bun machine
-> immutable bunfs base + one organization AgentFS writable delta
-> Bun.spawn of one native Hermes child per conversation holder
The Bun machine is shared by the supervisor; Hermes children are not. The Bun machine opens the organization AgentFS once and gives each Hermes child a conversation-scoped view of the same merged filesystem. AgentFS implements the writable copy-on-write delta: reads consult the delta before an intentionally exposed immutable bunfs asset, writes and new files go only to AgentFS, and a delete is represented directly by AgentFS. Packaged worker internals and the Hermes payload archive are not expanded into an agent-visible home. See the AgentFS overlay guide.
The lifecycle is:
- Organization provisioning creates its AgentFS and SessionDB authorities and establishes the private organization configuration and shared memory once.
- New-conversation establishment creates the conversation directory, writes
its private effective
.env,SOUL.md, andconfig.yamlonce, and creates a native Hermes session in the organization's existing SessionDB. - On cold supervisor startup, Zig confined-execs one resident Bun machine. That machine opens one local, sync-enabled AgentFS delta backed by the organization's existing cloud AgentFS. It does not provision a database per conversation or create a host workspace. Native Hermes keeps SessionDB as a separate organization database; SessionDB is not an AgentFS object.
- A conversation admission reuses that Bun machine and
Bun.spawns or reuses the conversation's native Hermes child. Warm turns resume the exact nativesession_id; they do not reopen AgentFS, run a hydrate/materialize helper, rebuild a prompt, or create another filesystem authority. - Cloud synchronization uses Turso's ordinary explicit sync operations. The
Bun machine performs a non-held
pull()before local agent work. After local filesystem work it performs anotherpull()so Turso atomically rolls back to the last synced state, applies remote changes, and replays unpushed local transactions, then callspush()when local CDC is pending. Turso's native last-push-wins rule resolves remote collisions. There is nolongPollTimeoutMs, background poll, Redis notification, application revision, ACP control frame, or Humanwork merge ledger. See the AgentFS sync guide and Turso conflict-resolution guide. - Orderly supervisor shutdown performs the same native pull/replay/push sequence for pending local AgentFS changes and closes that one AgentFS instance. SessionDB remains in its separate organization authority.
There is no host OSA home as session authority, host skill/workspace staging,
flat /.hermes-home, .humanwork/turns, machine-side config seeding, one-shot
hydrate/flush mode, local prompt/session cache, per-conversation database
provisioning, or fabricated session identity.
Removing host staging does not remove skills, shared memory, or durable conversation workspaces. Hermes reads and updates their canonical AgentFS objects directly; those mutations remain across warm turns and cold restarts. There is no host duplicate, quarantine mount, per-turn copy, reconcile, or flush-back step.
Ordinary Specialist or assignment offboarding is a routing/authority change, not a data purge. It must not acquire a database turn lease/fence, evict a resident holder, or mutate holder ownership merely to change routing, and it must not delete the Specialist's AgentFS database, SessionDB database, session index, transcript locator, or retained native memory. Retention expiry or a right-to-erasure purge is a separate, explicit, auditable operation with its own authority and exact targets; it is never inferred from offboarding.
6. Transcript and delivery are canonical, not projectedβ
Hermes supplies its own session and message locators. Humanwork stores and uses those exact locators; it does not substitute a conversation id, platform message id, or generated compatibility id as transcript identity.
Released edits update the exact canonical SessionDB assistant row identified by the Hermes locator. A genuinely human-authored reply with no Hermes row is appended once as a canonical SessionDB assistant row, and the returned locator becomes its identity.
New writes must not create <delivered_message> user-role envelopes,
projectedDeliveryIdentifiers, synthetic assistant projections, retry-appended
duplicates, or UI-only deduplication masks. Idempotency belongs at the canonical
SessionDB write boundary. Legacy same-content duplicates may be repaired;
conflicting prose must be surfaced as a conflict rather than silently hidden.
Hermes already records model tool calls in SessionDB, and AgentFS records every
filesystem operation and executed native tool call through its native ledger.
Humanwork must not copy those events into a second "local progress" or
turn-source ledger, infer them again from model history, or intercept ACP
updates to manufacture another audit stream. The Humanwork MCP gateway ledger
remains an operational receipt for external calls that actually traverse that
gateway (tenant authorization, idempotency, provider cost, and billing); it is
not the authority for Hermes' complete tool history and must not be repaired by
conversation/time inference. AgentFS timeline, diff, filesystem metadata, and
toolcalls SQL rows are the native audit authority; see the
AgentFS auditing guide.
Client-visible citations belong to Hermes' canonical reply/session evidence. Humanwork does not build a Sources footer by decrypting and projecting MCP gateway rows. A consumer that needs structured native evidence reads the existing Hermes/AgentFS records; it does not add a capture path to the turn.
7. Hermes is supervised through Bun.spawnβ
The resident session machine spawns Hermes through Bun.spawn. The removed
native exec/execveat helper is not a second process-management implementation.
The Bun path preserves:
- fd 3 for the raw machine channel and fd 4-7 for payload/memfd inputs;
- the existing environment, CA bundle, and provider/runtime variables;
- memfd-backed immutable payloads;
- byte-for-byte ACP stdin/stdout relay and raw fd reads;
- child exit, cancellation, signal, and orderly shutdown behavior.
The only deliberately abandoned property is "no procfs pathname appears in an exec path". It was not a product or correctness requirement and did not justify duplicating Bun's process lifecycle in native code.
8. The warm-turn critical path is intentionally smallβ
Before attaching a warm turn, Humanwork may authenticate the caller, persist the inbound message, resolve the existing Hermes session, route to the deterministic resident holder, and serialize that session's ACP turns inside the holder process. AgentFS and SessionDB authorities are consumed only while cold-establishing the supervisor; a warm admission carries no credential, token, environment, tool manifest, or configuration payload. The normal turn path does not acquire or renew a database assignment lease/fence; concurrent writers are prevented by holder affinity plus in-process per-session serialization.
Conversation, queue, transcript, and SessionDB freshness is event-driven.
Humanwork clients and services must not use interval polling,
periodic full-transcript rereads, timer-driven all-status snapshots, or
read-to-check-whether-anything-changed loops. A transcript mutation emits an
event carrying its exact Hermes locator so an authorized consumer can apply
the exact change or invalidate one scoped cache entry. AgentFS synchronizes
only at its native work boundaries using ordinary, non-held pull()/push();
idle time performs no sync request. Humanwork must not add a Redis subscriber,
invalidation event, revision, long poll, or ACP sync frame. An explicit user
open, reload, or refresh may perform one bounded authoritative read; idle time
performs none.
It must not synchronously retrieve KB, rebuild persona/skills, query mutable directives or response style, classify the task, derive a tool subset, seed a home, hydrate remote state, or render prompt text.
Phase timings must distinguish at least:
- API receipt to ACP attach;
- cold admission, when one occurs;
- first model request;
- model/tool loop;
- canonical persistence and delivery.
Warm latency is measured separately from cold admission. Increasing timeouts is not a performance fix.
9. Product defaults do not recreate a review gateβ
New Specialists use direct agent_reply delivery. The former Specialist,
assignment, organization, and message confidence/review columns are removed
from the current schema; no dormant compatibility value may recreate a reply
gate.
The local browser-demo seed includes a development-only Superadmin account and one-click Superadmin login alongside the client shortcut. Production remains protected by the existing demo-mode guard; no production authentication bypass is introduced.
Conversation rendering opens the session's cloud SessionDB authority directly, reads every canonical turn, and serializes those rows transiently into the authorized API response. Humanwork does not persist that serialization as a Postgres transcript, cache a mirrored prose history, or construct a UI projection. A new reply may not replace, hide, or regenerate the previous Specialist reply.
Consequencesβ
- A Humanwork turn is inspectable: the model receives the user's message, not a platform-authored composite prompt.
- KB and other context cost is paid only when Hermes chooses to retrieve it.
- Native capabilities remain available and MCP remains a true fallback/add-on.
- Successful replies cannot be trapped by a policy or compatibility state.
- There is one transcript representation and one session filesystem authority.
- Warm turns avoid remote hydration and repeated control-plane assembly.
- Tool schemas can shrink without deleting capabilities because Hermes owns progressive discovery.
- Offboarding preserves the native workspace and transcript until an explicit retention or purge action says otherwise.
- Native tool audit is recorded once, where Hermes and AgentFS already record it; the MCP ledger accounts only for calls that actually traverse MCP.
Required acceptance evidenceβ
This decision is complete only with all of the following:
- A test proving exact user text reaches ACP unchanged and the supervisor raw-relays native content blocks without parsing or narrowing them.
- A test proving an attachment is written once to cloud AgentFS and dispatched as its own standard ACP resource message referencing the AgentFS-visible object, with no R2/base64 copy, custom envelope, or attachment-to-text-row association.
- A warm multi-turn test proving one supervisor-resident Bun/AgentFS machine serves multiple conversation-scoped Hermes children and that no KB retrieval, prompt assembly, host-home write, AgentFS reopen, or helper process occurs after admission. It must prove plain pull/local-work/pull/push synchronization, no long poll/Redis/application revision/ACP parsing, zero push for read-only state, and a push for a Hermes mutation. Conflict tests must prove Turso pull preserves and replays unpushed local writes for both same-row and disjoint-row API/resident changes without an application merge.
- A cold-restart test proving the one supervisor AgentFS restores from its cloud authority and the separate native SessionDB transcript resumes.
- Tool tests proving normal browser/network/filesystem/shell/image tools remain reachable; the compiled-worker HyperSH Git smoke proving it is the primary native Git CLI over AgentFS and survives a cold restart; and proof that genuinely missing capabilities can be discovered through MCP.
- Tool-schema evidence proving Humanwork does not inject, remove, wrap, or task-narrow the schemas Hermes natively presents, including direct MCP schemas and any progressive disclosure Hermes itself performs.
- Delivery tests proving every successful reply delivers once with no
held_for_reviewor approval state. - Transcript tests proving exact-locator edit/append idempotency and the absence of new synthetic delivery envelopes/projections.
- Supervisor tests covering fd 3-7 mapping, env/CA/memfd behavior, raw relay,
cancellation, exit, and shutdown under
Bun.spawn, plus a patch-set guard proving no shipping patch modifies native Hermes ACP. - Fresh browser conversations covering the Percy 01-10 acceptance cases, reload persistence, and measured warm time-to-reply.
- Offboarding tests proving it neither takes a database turn lease/fence nor evicts or reassigns the resident holder merely for offboarding, and does not delete AgentFS/SessionDB Turso databases or their canonical index rows.
- Audit tests proving native calls do not create Humanwork
tool_call.local_progressortool_call.local_executionprojections and no reply Sources footer is reconstructed from the MCP gateway ledger. - Browser-demo tests proving the Superadmin shortcut is development-only, new Specialists default to direct replies, and two consecutive Specialist replies remain visible after reload.
- An idle-window test proving zero periodic application reads of conversation, queue, transcript, AgentFS, or SessionDB state. Transcript mutations update only their scoped consumer/cache entry by exact Hermes locator. AgentFS has no held request or background poll and no application event, invalidation, revision, or ACP sync signal.