Noolog Docs

Model health

A roster pins each agent to a model_name on a provider. Providers retire ids, rename them, and sometimes advertise ids they will not serve — and a dead id fails every request the agent is ever given. An agent therefore judges its own model and benches itself, so the scheduler stops assigning it work.

There are two detectors, and they answer different questions.

Detector Question
Reactive ModelDownDetector Did the task that just failed fail because the model is gone?
Proactive ModelAvailability Is the model usable before a task is spent finding out?

Reactive detection alone means the first caller routed to a dead seat pays for the discovery. The proactive probe exists so nobody does.

What the proactive probe checks

One free request, throttled to once every five minutes: fetch the provider's OpenAI-compatible /models list and look for the id. A successful fetch that omits it is a verdict.

ModelAvailability::new(format!("{base}/models"), provider_id)

The probe never sends a completion. A catalog is an advertisement — a provider can list an id whose /chat/completions answers 404 — but confirming that costs a billed request per seat per interval, and a fleet doing so paid for a token on every tick. A listed-but-unserved model is instead caught by the reactive detector on its first real task.

Context length from the same catalog

The probe also reads each entry's stated context length — context_length (OpenRouter), then max_context_length, then context_window, then top_provider.context_length — and quorum serve pushes the agent's context_window to that value at startup, in both directions: an understated yaml wastes context the provider serves (the shrink-guard clamps output against the stated window), an overstated one ships requests the provider rejects. The catalog, not the yaml, is the authority on what the provider serves. When the catalog is unreachable or its entry states no context field, the configured value stands (fail-open); the change is logged as context_window set from provider catalog.

Fail-open is the invariant

Availability::Unavailable is returned only when the provider says the model is not there — omitted from a successfully fetched catalog. Everything else is Availability::Unknown, which never benches:

  • a catalog fetch that failed
  • a rate limit, an auth failure, a provider 5xx, a transport error
  • an agent on a provider this probe does not cover
  • a probe that has not run yet

The reason is blunt: every agent in a fleet shares a provider, so a rule that benched on any error would turn one provider hiccup into a total outage. A model that is briefly unreachable keeps serving; only one that is reported gone stops.

Benching

A verdict of Unavailable arms model_down for an escalating cooldown — repeat strikes bench progressively longer, capped — and the heartbeat reports model_down while the deadline stands. The scheduler excludes a down-model agent from assignment even while it is otherwise online, and the bench clears on expiry so a transient outage does not sideline an agent permanently.