# How ModLens Chains Vision Providers for Failover: Provider Selection Logic Explained

> Discover how ModLens chains vision providers for failover. Learn about its provider selection logic, prioritizing local over remote and respecting user preferences for a robust sequence.

- Repository: [liustack/modlens](https://github.com/liustack/modlens)
- Tags: architecture
- Published: 2026-08-25

---

**ModLens builds a prioritized provider chain in [`src/providers/availability.ts`](https://github.com/liustack/modlens/blob/main/src/providers/availability.ts) that filters available providers by binary presence or API credentials, orders them by input type (local vs remote), and inserts user preferences at the front to create a robust failover sequence.**

The open-source ModLens project (liustack/modlens) implements a sophisticated provider selection system that ensures reliable vision analysis across diverse environments. By dynamically constructing a provider chain based on real-time availability checks and user configuration, ModLens guarantees that image analysis proceeds even when primary providers fail.

## Understanding the Provider Availability System

At the core of ModLens’s failover capability lies a strict availability validation system. Before any provider enters the execution chain, the system verifies that all prerequisites are satisfied.

### Provider Descriptors and Type Classification

Each vision provider in ModLens is defined by a **provider descriptor** that specifies its operational type—either `subprocess` for local CLI tools or `api` for remote endpoints. These descriptors declare required binaries (such as `antigravity-cli` or `claude-cli`) or mandatory API settings including `apiKey`, `baseUrl`, and `model`. This metadata allows ModLens to determine, before execution, whether a provider can possibly succeed given the current environment configuration.

### The Availability Check Mechanism

The function `providerAvailable()` (lines 9-26 in [`src/providers/availability.ts`](https://github.com/liustack/modlens/blob/main/src/providers/availability.ts)) performs the gatekeeping logic for the failover chain. For subprocess providers, it checks that the binary exists on `PATH`. For API providers, it validates that all required configuration fields are present and non-empty. Only providers passing this availability check are eligible for inclusion in the final execution chain.

## Building the Failover Chain

ModLens constructs the provider chain through a multi-stage filtering and reordering process that balances performance, reliability, and user preference.

### Static Failover Orders for Input Types

The system maintains two distinct static orderings defined in [`src/providers/availability.ts`](https://github.com/liustack/modlens/blob/main/src/providers/availability.ts):
- **`LOCAL_FAILOVER_ORDER`** (lines 36-42): Prioritizes fast inline API providers (`gemini-api`, `openai`, `anthropic`) before falling back to `antigravity-cli` and finally `claude-cli` for local file inputs.
- **`REMOTE_FAILOVER_ORDER`** (line 49): Uses a similar priority structure optimized for remote URL inputs, ensuring network-efficient providers are attempted first.

These predefined sequences ensure that cloud-based APIs—typically faster and more capable—are exhausted before attempting local subprocess executions.

### User Preference Injection

When a user specifies a default provider via `config.provider`, the logic in lines 71-86 resolves the canonical provider name and reorders the chain. The preferred provider is moved to the front of the array, ensuring it receives first priority. This user-override mechanism allows consistent use of specific backends without disabling the safety net of failover alternatives.

### Pin-Only Providers and Chain Construction

Certain providers like `kimi-cli` operate as **pin-only** entries—they are excluded from the default chain unless explicitly requested. The `providerChain()` function (lines 58-63 and 98-102 in [`src/providers/availability.ts`](https://github.com/liustack/modlens/blob/main/src/providers/availability.ts)) orchestrates the final assembly:

1. Selects the base order (`LOCAL_FAILOVER_ORDER` or `REMOTE_FAILOVER_ORDER`) based on input type.
2. Applies the `reuse.claude` configuration flag to optionally omit `claude-cli` from the sequence.
3. Injects the user-preferred provider at the chain’s head or as a pinned entry.
4. Filters by availability using `providerAvailable()`.
5. Resolves each name to its concrete `VisionProvider` implementation via `resolveProvider()` from [`src/providers/index.ts`](https://github.com/liustack/modlens/blob/main/src/providers/index.ts).

The resulting array is consumed by [`src/analyzer.ts`](https://github.com/liustack/modlens/blob/main/src/analyzer.ts), which iterates sequentially until successful completion.

## CLI Failover Configuration Examples

The following commands demonstrate practical failover scenarios using ModLens’s provider selection system:

```bash

# Use the default provider (antigravity-cli). If it fails,

# ModLens will automatically fall back to the next available API.

modlens -i screenshot.png

```

```bash

# Prefer the OpenAI compatible endpoint. It is placed first

# in the chain, but if the API key is missing or the call fails,

# ModLens will try Gemini, then Anthropic, then antigravity-cli.

modlens -i screenshot.png -p openai

```

```bash

# Set a global default provider (persisted in the config).

# The chosen provider is moved to the front of the chain for all runs.

modlens config set provider gemini-api
modlens -i screenshot.png          # gemini-api is tried first

```

```bash

# Disable Claude CLI reuse (useful when the user does not want

# to spend a Claude subscription). The chain then omits claude-cli.

modlens config set reuse.claude false
modlens -i localfile.png           # chain: gemini-api → openai → anthropic → antigravity-cli

```

```bash

# Pin-only provider: request Kimi CLI explicitly. It is added

# only when requested and runs before any other local providers.

modlens -i screenshot.png -p kimi-cli

```

## Key Source Files and Functions

- **[`src/providers/availability.ts`](https://github.com/liustack/modlens/blob/main/src/providers/availability.ts)** – Contains `providerAvailable()` for prerequisite validation and `providerChain()` for building the ordered failover sequence.
- **[`src/providers/index.ts`](https://github.com/liustack/modlens/blob/main/src/providers/index.ts)** – Exports `resolveProvider()` to map provider names to concrete implementation objects.
- **[`src/config.ts`](https://github.com/liustack/modlens/blob/main/src/config.ts)** – Stores user preferences including `provider` and `reuse.claude` flags that influence chain ordering.
- **[`src/analyzer.ts`](https://github.com/liustack/modlens/blob/main/src/analyzer.ts)** – Orchestrates the iteration over the constructed provider chain to execute vision analysis.

## Summary

- ModLens implements **provider availability checking** in [`src/providers/availability.ts`](https://github.com/liustack/modlens/blob/main/src/providers/availability.ts) before adding any provider to the execution chain.
- The system uses **distinct failover orders** for local files (`LOCAL_FAILOVER_ORDER`) versus remote URLs (`REMOTE_FAILOVER_ORDER`) to optimize for latency and capability.
- **User preferences** specified via `config.provider` are dynamically injected at the front of the chain while preserving fallback options.
- **Pin-only providers** like `kimi-cli` are excluded from automatic selection unless explicitly requested via CLI flags.
- The analyzer in [`src/analyzer.ts`](https://github.com/liustack/modlens/blob/main/src/analyzer.ts) executes providers sequentially until successful completion, ensuring robust fault tolerance.

## Frequently Asked Questions

### How does ModLens determine if a provider is available for the failover chain?

ModLens calls `providerAvailable()` in [`src/providers/availability.ts`](https://github.com/liustack/modlens/blob/main/src/providers/availability.ts) (lines 9-26), which checks that subprocess binaries exist on `PATH` or that API providers have required configuration fields (`apiKey`, `baseUrl`, `model`) populated. Only providers passing this validation are included in the final chain.

### What happens if my preferred provider fails during execution?

If the provider specified via `-p` or `config.provider` fails, ModLens automatically proceeds to the next available provider in the chain. The system maintains the complete ordered list from `LOCAL_FAILOVER_ORDER` or `REMOTE_FAILOVER_ORDER` (minus unavailable providers), ensuring seamless failover to alternatives like `gemini-api`, `anthropic`, or `antigravity-cli`.

### Can I exclude specific providers from the failover sequence?

Yes. You can disable `claude-cli` specifically by setting `reuse.claude` to `false` in the configuration, which removes it from the chain. Additionally, providers marked as pin-only (such as `kimi-cli`) never appear in the default chain unless explicitly requested with the `-p` flag.

### Where does ModLens store the logic for resolving provider names to implementations?

The resolution occurs in [`src/providers/index.ts`](https://github.com/liustack/modlens/blob/main/src/providers/index.ts), which exports `resolveProvider()`. This function maps canonical provider names (like `openai` or `gemini-api`) to their concrete `VisionProvider` class instances that perform the actual image analysis.