Skip to main content

Role-based model binding

Use when code names a model. Bind models to roles. Owner rule (2026-09-13, applies to every build): components are named by role; models are plugged in. No adapter, module, class, filename, doc, contract, task, or prompt may be model-specific.

Required shape​

  • Name by role: broker, reviewer, coordinator, verifier, implementer, escalation_reviewer. Never sol_*, opus_*, astra_*, fable_*, terra_*.
  • A role binds a route (provider/model) at assignment time, from configuration or the coordinator's signed assignment — never a module constant.
  • Keep one approved-route allowlist in config. Adding a model is a config/allowlist change plus a transport capability, not an edit to role logic.
  • Provider-specific wire behavior (auth shape, streaming/event format, completion validation) lives in a small pluggable transport behind one stable interface. The role/broker code stays provider-neutral.
  • Every receipt, binding, and log records the exact actual provider/model used, plus the transport id. Interchangeable at assignment; precisely identified afterwards.
  • Pool equivalence is owner policy, not code opinion: Opus == Sol, Fable == Astra. If one member is unavailable (429/quota, logged out, unroutable), the other fills that role immediately. Blocked requires BOTH failing, with per-member evidence.

Forbidden​

  • ROUTE = 'provider/model' or APPROVED_ROUTE = ... as a module constant.
  • A transport hardcoded to one vendor's endpoint/response schema with no interface seam.
  • Model names in filenames, contract docs, task titles, or cron prompts when a role name would do.
  • Silent fallback inside a single attempt: pool selection happens at assignment; an in-flight attempt keeps its bound route and fails honestly.

Substitution never relaxes anything​

Swapping the bound model must not reset attempt lineage or escalation counts, weaken isolation/budgets/output validation, merge reviewer and implementer executions, or grant merge authority. Changing the binding changes the policy identity, so the assignment/policy digest must be reconciled — never rewrite sealed history.

When you find a violation​

Do not add a second hardcoded constant beside the first. Extract the seam: role module + route parameter + transport registry + allowlist, with tests proving two different bound routes drive the same role through identical enforcement.

Why this rule exists​

AF-34 (2026-09-13) stalled for a full day because sol_broker.ROUTE and reviewer_isolation.APPROVED_ROUTE pinned one vendor route. When that credential hit usage_limit_reached (5+ day window), an authenticated equivalent model existed and was owner-approved, but no code path could bind it — so the fleet emitted capacity-blocked reports instead of delivering. A hardcoded route converts a routine provider outage into a multi-day delivery outage.


Source: jknash/hermes-shared-skills · branch hermes-jkdev001 @ 1d0d545c3970 · skills/engineering/role-based-model-binding/ · view source · Imported 2026-10-03. Supporting files (references, scripts) remain in the source repository.

version 1.0.0 · author jknash, Hermes Agent · license MIT.

Published by Muse · 2026-10-03.