Module: AgentHarness::ModelCompatibility

Defined in:
lib/agent_harness/model_compatibility.rb

Overview

Structured runner/model compatibility contract.

ModelCompatibility is the single source of truth for whether a given runner (provider) can execute a particular model under specific runtime constraints such as authentication mode or installed CLI version. Downstream orchestrators (for example Paid's RDR-040 tier-to-model mapping) consume this contract before validating tier models, selecting runners, and starting agent runs — instead of inferring compatibility from scattered facts like CLI version pins, smoke-test overrides, or observed runtime errors.

Examples:

Query Codex compatibility for a CLI-gated model

AgentHarness.model_compatibility(
  runner: :codex,
  model_id: "gpt-5.5",
  auth_mode: :subscription,
  cli_version: "0.116.0"
)
# => #<AgentHarness::ModelCompatibility::Result supported=true ...>

Defined Under Namespace

Classes: Result

Constant Summary collapse

UNKNOWN_REASON =

Sentinel for "the runner declares no opinion about this model."

:unknown
UNKNOWN_MODEL_REASON =

Issued when a runner does not advertise the requested model at all.

:unknown_model
UNKNOWN_CLI_VERSION_REASON =

Issued when the runner needs a comparable CLI version to answer definitively for a CLI-gated model but the caller did not supply one (or it could not be parsed). Pairs with :minimum_cli_version on the result. Distinct from :unknown_model — the runner does know the model; it just cannot confirm the installed CLI is new enough.

:cli_version_unknown
UNKNOWN_AUTH_MODE_REASON =

Issued when the runner needs an auth mode to answer definitively for an auth-gated model but the caller did not supply one. Pairs with :supported_auth_modes on the result details. Distinct from :unknown_model — the runner does know the model; it just cannot confirm the requested auth mode is allowed for it.

:auth_mode_unknown
UNSUPPORTED_CLI_VERSION_REASON =

Issued when the runner supports the model but the installed CLI is too old. Pairs with :minimum_cli_version on the result.

:cli_version_too_old
UNSUPPORTED_AUTH_MODE_REASON =

Issued when the runner supports the model but the requested auth mode is not part of the runner's contract for it.

:auth_mode_not_supported
UNSUPPORTED_AUTH_MODE_FOR_MODEL_REASON =

Issued when the runner accepts the requested auth mode generally, but the specific model is not available under that auth mode.

:unsupported_auth_mode_for_model
SUPPORTED_REASON =

Default supported reason.

:supported
SOURCES =

Sources for a compatibility decision. Static contracts are baked into the provider; live probes hit the provider CLI/API; entitlement checks gate on subscription state. Downstream orchestrators can use this to decide whether to cache the answer.

%i[static_contract live_provider_probe entitlement_check unknown].freeze

Class Method Summary collapse

Class Method Details

.build_result(runner:, model_id:, **attributes) ⇒ Result

Build a Result with sensible defaults from a partial Hash.

Provider implementations call this helper to return a normalized Result without having to instantiate Struct fields by hand.

Parameters:

  • runner (Symbol)

    canonical provider/runner name

  • model_id (String, Symbol, nil)

    requested model id

  • attributes (Hash)

    additional Result attributes

Returns:



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/agent_harness/model_compatibility.rb', line 99

def build_result(runner:, model_id:, **attributes)
  normalized_model_id = model_id.is_a?(Symbol) ? model_id.to_s : model_id
  source = attributes.fetch(:source, :static_contract)
  supported = attributes[:supported]

  if supported == false && attributes[:reason].nil?
    raise ArgumentError,
      "AgentHarness::ModelCompatibility.build_result requires an explicit " \
      "`reason:` when `supported: false`. Pass a specific reason " \
      "(e.g. :cli_version_too_old, :auth_mode_not_supported) so " \
      "callers can distinguish unsupported from :unknown."
  end

  reason = attributes[:reason] || default_reason_for(supported)

  Result.new(
    runner: runner.to_sym,
    model_id: normalized_model_id,
    auth_mode: attributes[:auth_mode],
    cli_version: attributes[:cli_version],
    supported: supported,
    reason: reason,
    minimum_cli_version: attributes[:minimum_cli_version],
    cli_version_requirement: attributes[:cli_version_requirement],
    fallback_model_id: attributes[:fallback_model_id],
    source: source,
    details: attributes[:details]
  )
end

.unknown_result(runner:, model_id:, fallback_model_id: nil, **attributes) ⇒ Object

Build an explicit "unknown" Result. Use when the runner has no static contract for the requested model and cannot probe.



131
132
133
134
135
136
137
138
139
140
141
# File 'lib/agent_harness/model_compatibility.rb', line 131

def unknown_result(runner:, model_id:, fallback_model_id: nil, **attributes)
  build_result(
    runner: runner,
    model_id: model_id,
    supported: nil,
    reason: attributes.delete(:reason) || UNKNOWN_REASON,
    fallback_model_id: fallback_model_id,
    source: attributes.delete(:source) || :unknown,
    **attributes
  )
end