Skip to content
UHPUHPDeveloper Guide
Independent resource · Not affiliated with HarnessRouter · Site data checked 19 Sep 2026

Harness architecture

Routing Identity in Multiplexed Agent Harnesses

A multiplexed harness should not independently rediscover who received an event, who may authorize it, where it executes and which session namespace owns it. Resolve those coordinates once at ingress, preserve the result across copies and deferred work, and make every owner-sensitive derivation consume the same identity.

Verified: Evidence: Hermes PRs #115665 + #115666Protocol: 2026-09-12

A multiplexed agent gateway can have several valid ownership coordinates for one inbound event: the profile that owns the receiving transport, the profile authorized to admit the request, the profile that executes the turn, the home/configuration root used at runtime and the namespace used for session keys and persistence. Those coordinates may be related without being identical.

The dangerous design is to derive them independently at different stages. A route can be admitted correctly, then an adapter can build a queue key before the runner stamps the routed profile, or a later authorization/runtime lookup can fall through a different fallback chain. The result is a split identity: the same event is treated as belonging to different owners by different subsystems.

Nous Research merged Hermes PR #115665 on 19 September 2026 as ad651b825076d31f66cf77c76304c60ab5511a66, introducing one frozen RoutingIdentity per inbound gateway event. PR #115666, merged immediately afterward as c07708671d2952f1790f696fc134b1cb8b54ea96, routes adapter-side session-key derivation through one owner-aware seam so queues, batching and busy-state keys agree with the runner.

These are post-v0.21.3 current-main Hermes implementation changes. They do not revise UHP, MCP, ACP or A2A wire semantics, do not change Hermes’ serialized SessionSource.profile field or historical session-key format, and do not establish native UHP adoption by Hermes.

Identity is a tuple, not one profile string

Section titled “Identity is a tuple, not one profile string”

Hermes’ current-main RoutingIdentity makes the distinction explicit. It carries:

CoordinateMeaning
transport_profileprofile that owns the receiving adapter/credential
runtime_profileprofile whose agent/runtime executes the turn
authorization_homehome whose admission policy authorizes the source
runtime_homehome/configuration root used by the executing runtime
multiplexedwhether multiplex ownership rules apply
transport provenanceweak reference to the live receiving transport; provenance, not identity equality

The object also exposes derived session/store coordinates such as the namespace and session_key_profile. Inside the identity, the default owner is explicit rather than encoded as an ambiguous None fallback.

That matters because transport owner and runtime owner can legitimately differ. A shared bot may receive a message under one profile and route it to a satellite profile for execution. Treating either coordinate as the universal owner would erase information required by authorization, runtime scoping or persistence.

PR #115665 centralizes the decision in resolve_identity(...). The runner uses that path when admitting primary sources and when stamping routed secondary events. Once resolved, the frozen identity is pinned to the source as wire-invisible process-local state.

The important architectural property is not the Python dataclass itself. It is the ordering rule:

  1. observe the transport and requested/routed destination;
  2. resolve the full owner tuple once;
  3. fail explicitly when the route cannot be resolved under multiplexing;
  4. attach that decision to the work item; and
  5. make downstream readers consume it rather than independently repeating route/default logic.

Under multiplexing, Hermes now raises IdentityUnresolved for a rejected route instead of allowing an unresolved value to mean “default”. Outside that path, legacy/restored/hand-built sources can still use compatibility fallbacks. That boundary is deliberate: the merged work strengthens canonical ingress without pretending every historical producer has already been rewritten.

Every owner-sensitive reader must consume the same decision

Section titled “Every owner-sensitive reader must consume the same decision”

After #115665, the pinned identity is the first source for several previously independent readers:

  • transport-owner lookup;
  • authorization-home lookup;
  • runtime-home/profile resolution;
  • adapter-side session-key profile selection; and
  • session-store profile resolution.

Copies of a source use the identity-aware replacement helper so transport provenance and the frozen routing decision survive the copy. A normal dataclasses.replace(...) would otherwise copy declared fields while dropping dynamic provenance.

This is a general multi-tenant runtime rule: once an event has crossed an ownership/admission boundary, later code should carry the admitted identity forward rather than asking ambient process state to answer the ownership question again.

Session keys expose split identity quickly

Section titled “Session keys expose split identity quickly”

PR #115666 demonstrates why canonical identity is useful only if derived keys also pass through a single seam. Before the fix, Yuanbao’s dispatch middleware called the free build_session_key(source) without a profile. For a secondary-owned bot, its per-group dispatch queue and RecallGuard bookkeeping therefore landed under agent:main: while the runner handled the same message under agent:<owner>:.

The upstream red probe records the mismatch explicitly for owner acme:

  • adapter queue key before the fix: agent:main:yuanbao:group:grp-1:u1;
  • owner-aware seam key: agent:acme:yuanbao:group:grp-1:u1.

That is not a cosmetic prefix error. Two bots can then share a serial queue or busy/recall state that should have been owner-scoped, while the actual turn is stored and executed in another namespace.

Current-main Hermes now sends adapter-side key construction through BasePlatformAdapter._source_session_key / _event_session_key. The same seam absorbs the Weixin text-batch path, Telegram photo/album batching, Slack thread keys and Raft wake keys. An advisory CI pattern, P32, flags free build_session_key( and direct SessionSource( construction under adapter directories except the canonical base seam.

Canonicalization still has a documented boundary

Section titled “Canonicalization still has a documented boundary”

The merged work does not claim that every possible source constructor in Hermes has already been eliminated. PR #115666 reports four remaining direct SessionSource( hits in adapter code and says they are intentionally left for a later phase. P32 is advisory, not a hard CI prohibition.

Similarly, PR #115665 keeps old fallback readers for sources that did not pass through canonical resolution. This makes the migration additive and preserves historical behavior, but it also means the strongest invariant applies to events that enter through the canonical ingress paths.

A reliable architecture page should preserve that distinction: one canonical identity path exists and the reviewed ingress/adapter paths use it; complete removal of all legacy construction/fallback paths is not yet established at this cutoff.

The upstream validation reported for #115665 includes:

  • three focused identity invariants covering reader agreement, unresolved multiplex routing versus explicit default behavior, and identity-preserving source copies;
  • a real runner A→B→A sequence across two homes and a shared-bot route, where identity, ambient HERMES_HOME, authorization home, adapter key and runner key agree without cross-turn contamination;
  • 9,846 passed, 0 failed, 0 flaky across the stated gateway/scripts/platforms test command; and
  • clean lint/compatibility/diff checks.

PR #115666 adds a red-before/green-after adapter-key regression over both default and owner acme, plus P32 checker tests. Its stacked validation reports the same 9,846 passed, 0 failed, 0 flaky broad command.

Those are upstream implementation results, not independent benchmarking by this site. PR #115666 merged as c07708671d2952f1790f696fc134b1cb8b54ea96; the final pre-publication drift check observed Hermes main at 9dee8863e15574a3a3770bc77ee289eb482f878d, after later unrelated model-switch documentation, without invalidating the reviewed routing commits. The latest stable release remains v2026.9.14 / Hermes Agent v0.21.3.

  1. Resolve ownership once at admission. Transport, authorization, runtime and persistence coordinates should come from one explicit routing decision, not several ambient fallback chains.
  2. Keep distinct coordinates distinct. Transport owner and runtime owner may legitimately differ; preserving both is safer than collapsing them into one overloaded profile field.
  3. Fail unresolved multiplex routes closed. “Could not resolve owner” must not silently become the default owner in a multi-profile process.
  4. Derive keys from the admitted identity. Queues, batching, busy-state maps, persistence keys, caches and recovery maps must use the same owner seam as execution.
  5. Preserve identity across copies and deferred handoffs. Copying only serialized/public fields can discard process-local provenance that later authorization or routing needs.
  6. Make the default owner explicit internally. Null sentinels are dangerous when the same null can mean default, unknown or wildcard in different layers.
  7. Test with conflicting owners. A strong regression gives two profiles distinct homes and routes A→B→A; success alone is insufficient if both accidental owners would also work.
  8. Lint secondary derivations. Canonicalization erodes when adapter/plugin authors can freely reconstruct session keys or source objects beside the official seam.

A multiplexed harness should be able to demonstrate at least these cases:

  • shared transport owned by A routes execution to B → authorization remains bound to the admitting transport owner where intended, runtime/home/session namespace resolve to B, and every key reader agrees;
  • unresolved/rejected route while multiplexing → event is dropped or explicitly rejected, never executed under default;
  • default/non-multiplexed event → historical default namespace remains byte-stable;
  • source copied for deferred/background work → routing identity and transport provenance survive the copy;
  • secondary-owned bot uses per-chat/group batching → queue key equals the owner-aware runner/session key rather than agent:main:;
  • two secondary bots share the same external chat/group id → their queue/busy/recall state remains isolated by owner namespace; and
  • canonical adapter code introduces a free session-key derivation or direct source constructor → static analysis/test evidence identifies the second seam before release.

Profile isolation asks a broader question: do secrets, configuration, MCP connections, child environments, background work, persistence and delivery remain inside the correct owner scope across the whole lifecycle?

Routing identity is one enabling mechanism for that invariant. It does not replace owner-scoped secret resolution, scoped caches, destination-owned child environments or deferred-work context propagation. Instead, it provides a durable answer to the question those subsystems repeatedly need: which ownership coordinates were actually admitted for this work item?

This page documents a harness-runtime architecture pattern using current Hermes source evidence.

  • UHP: does not standardize Hermes profiles, RoutingIdentity, HERMES_HOME or Hermes session-key prefixes. A UHP server may multiplex internal harness instances, but UHP does not acquire these local owner coordinates from PRs #115665/#115666.
  • MCP: may be one resource controlled by an owner-scoped runtime, but these merges do not change MCP transport, authentication or tool semantics.
  • ACP: may carry session/control messages to an agent runtime, but these merges do not change ACP session identifiers or wire behavior.
  • A2A: is unchanged; Hermes’ local gateway routing identity does not become an A2A agent-identity primitive.
  • HarnessRouter: current HarnessRouter remains v0.18.4 / efd320b313891191967871de28ff4757528ae6a7; nothing in these Hermes merges is new HarnessRouter conformance evidence or native Hermes UHP adoption.

This is an independent technical guide. “Routing identity” here is an architectural description grounded in the cited Hermes implementation; it is not a new interoperability standard or a vendor certification.