The harness router resolves which Harness adapter and model to use for each turn by layering approval, org-level and scope-level config, and caller intent, then falls back safely when the configured choice is unavailable. Wrapping multiple adapters behind a single Harness interface, the router handles session transitions between harnesses, sources metadata from a utility adapter, and manages lifecycle operations across the adapter set. The OpenRouter model catalog is a term-of-art dependency: it is a remote list of available models fetched at runtime and cached; absence of a warm cache is called a "cold" resolution.
src/harness/harness-router.ts exports resolveRuntimeChoice, which resolves the harness and model to use for a turn by layering: approved harness list → org-level stored/legacy config → scope-level stored/legacy config → explicit caller request. A scope-level runtime selection is only consulted when scope !== orgScopeId; at org scope the scoped values are set to null, preventing the org's own record from being applied twice.[1] If the final resolved choice is not approved, a NonRetryableTurnError is thrown when the caller explicitly requested that choice; otherwise resolution falls back to the org-level choice.[1] When the configured fallback harness is not in the approved list or its model is unsupported, safeFallback is recalculated using the first approved harness ID and defaultModelForHarness(firstApproved, fallback.modelId) — preventing a provider-blind fallback from silently failing all turns.[1] resolveRuntimeChoiceDurable is an async variant that fetches all config values (approved harnesses, stored runtime selections, base models) concurrently via Promise.all and then delegates to the synchronous resolver.[1] In src/harness/harness-router.ts and src/wiring.ts, the OpenRouter model catalog is fetched and hydrated synchronously within the model-resolution path on the first (cold) resolution, so catalog fetch latency or failure surfaces at model selection time rather than at startup.
src/harness/harness-router.ts also exports createHarnessRouter, which wraps multiple Harness adapters behind a single Harness interface, resolving the correct adapter on each turn via an injected resolve callback.[1] When the session's harness has changed since the last turn, createHarnessRouter calls resetSession on both the old and new harness before running the turn.[1] profile, models, and tools on the router are sourced from an injected utility harness, making the router's metadata surface independent of which adapter handles any given turn.[1]
Calling resetSession on the harness router deletes the session's last-harness record and broadcasts resetSession to all registered adapters in parallel via Promise.all.[1] Calling close on the harness router deduplicates adapters via new Set before invoking close on each, preventing a double-close when multiple harness IDs share the same adapter instance.[1]
Sources