# How to Select Different LLM Providers in Chapter CLIs

> Learn how to select different LLM providers in chapter CLIs by exploring the centralized provider registry in bojieli/ai-agent-book. Use the --provider flag for easy selection.

- Repository: [Bojie Li/ai-agent-book](https://github.com/bojieli/ai-agent-book)
- Tags: how-to-guide
- Published: 2026-08-22

---

**The chapter CLIs in `bojieli/ai-agent-book` obtain their selectable LLM providers from the centralized provider registry in [`agentbook/providers/registry.py`](https://github.com/bojieli/ai-agent-book/blob/main/agentbook/providers/registry.py), exposing them via the `--provider` command-line flag.**

Every chapter-specific CLI in this repository shares a unified mechanism for selecting large language model backends. Rather than hardcoding provider endpoints in each script, the codebase leverages a single registry that defines canonical providers, aliases, and supported choices. This architecture allows you to switch between providers like DashScope, OpenRouter, or Moonshot using a consistent interface across all chapters.

## How the Provider Registry Works

The registry located at [`agentbook/providers/registry.py`](https://github.com/bojieli/ai-agent-book/blob/main/agentbook/providers/registry.py) serves as the authoritative source for all LLM provider configurations in the project. When you select a provider via command line, the CLI validates your choice against this central registry.

### The PROVIDERS Dictionary

The `PROVIDERS` dictionary holds the canonical definitions for each supported LLM service. Each entry specifies the provider name, API endpoint, default model, and required environment variables for authentication. This dictionary acts as the single source of truth for provider capabilities and connection parameters.

### Alias Mapping with _ALIASES

The `_ALIASES` dictionary maps short or historic names to their canonical entries. For example, the alias `moonshot` resolves to the canonical provider `kimi`, while `ark` and `google` map to their respective canonical configurations. This allows users to invoke familiar shorthand names while the system internally resolves them to standardized definitions.

### SUPPORTED_PROVIDERS Tuple

The `SUPPORTED_PROVIDERS` tuple is pre-computed to include every canonical provider name plus every registered alias. Chapter CLIs import this tuple directly from `agentbook.providers.registry` and pass it to `argparse` as the `choices` parameter for the `--provider` argument. Because the CLIs reference this tuple dynamically, any provider added to the registry immediately becomes selectable without modifying individual CLI scripts.

## Using the --provider Flag in Chapter CLIs

Every chapter CLI follows the same pattern for exposing provider selection. For example, the execution tools CLI in chapter 4 defines its provider argument as:

```python

# chapter4/execution-tools/cli.py

parser.add_argument(
    "--provider",
    help="LLM 提供商（覆盖 PROVIDER，如 dashscope/qwen/bailian/kimi/doubao/siliconflow/openrouter）",
)

```

The `choices` parameter is automatically populated with `SUPPORTED_PROVIDERS`, restricting input to valid registry entries. You can invoke any chapter CLI with your preferred backend:

```bash

# Use the default provider (openrouter)

python -m chapter4.execution-tools.cli ...

# Switch to DashScope (Alibaba Cloud)

python -m chapter4.execution-tools.cli --provider dashscope ...

# Use the Moonshot alias (resolves to kimi)

python -m chapter4.execution-tools.cli --provider moonshot ...

# Short flag variation (if implemented in the specific CLI)

python -m chapter4.execution-tools.cli -p siliconflow ...

```

## Step-by-Step Provider Resolution

When you specify a provider via the command line, the system executes a five-stage resolution pipeline:

1. **Registry Import** – The CLI imports `SUPPORTED_PROVIDERS` from `agentbook.providers.registry`, which evaluates the current state of `PROVIDERS` and `_ALIASES`.

2. **Argument Validation** – `argparse` validates your input against the `choices=SUPPORTED_PROVIDERS` constraint, rejecting invalid names before execution continues.

3. **Canonicalization** – The code calls `canonical_provider(name)` from the registry module to resolve any alias to its canonical key (e.g., converting `moonshot` to `kimi`).

4. **Specification Lookup** – The canonical name is passed to `lookup(canonical)`, which returns the provider dataclass containing endpoint URLs, default models, and required environment variables.

5. **Backend Instantiation** – Finally, `resolve_backend(provider, model, ...)` from [`agentbook/providers/resolution.py`](https://github.com/bojieli/ai-agent-book/blob/main/agentbook/providers/resolution.py) constructs the concrete client object, injecting API keys from environment variables and configuring the appropriate endpoint.

This resolution chain ensures that selecting different LLM providers in chapter CLIs requires only a single flag change, while the underlying machinery handles authentication and endpoint configuration automatically.

## Programmatic Provider Selection

You can also select providers programmatically within chapter scripts for dynamic backend switching:

```python
from agentbook.providers.registry import lookup, canonical_provider, SUPPORTED_PROVIDERS
from agentbook.providers.resolution import resolve_backend

# Validate user input against supported choices

user_input = "moonshot"
if user_input not in SUPPORTED_PROVIDERS:
    raise ValueError(f"Provider must be one of: {SUPPORTED_PROVIDERS}")

# Resolve alias to canonical name

canonical = canonical_provider(user_input)          # Returns "kimi"

# Retrieve provider specification

provider_spec = lookup(canonical)                  # Provider dataclass with config

# Instantiate backend client

backend = resolve_backend(canonical, model=None)   # Returns configured client

```

## Summary

- **Centralized registry**: All provider definitions live in [`agentbook/providers/registry.py`](https://github.com/bojieli/ai-agent-book/blob/main/agentbook/providers/registry.py), making `PROVIDERS` and `SUPPORTED_PROVIDERS` the single source of truth.
- **Alias support**: The `_ALIASES` mapping allows shorthand names like `moonshot` to resolve to canonical providers like `kimi`.
- **Automatic CLI updates**: Chapter CLIs reference `SUPPORTED_PROVIDERS` directly, so new providers added to the registry instantly appear as valid `--provider` choices.
- **Canonical resolution**: The `canonical_provider()` function normalizes aliases before `resolve_backend()` constructs the authenticated client.
- **Consistent interface**: Every chapter CLI (e.g., [`chapter3/dense-embedding/cli.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter3/dense-embedding/cli.py), [`chapter7/elo-leaderboard/cli.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter7/elo-leaderboard/cli.py)) uses the same `--provider` flag pattern.

## Frequently Asked Questions

### Where is the provider registry defined?

The provider registry is defined in [`agentbook/providers/registry.py`](https://github.com/bojieli/ai-agent-book/blob/main/agentbook/providers/registry.py). This file contains the `PROVIDERS` dictionary with canonical definitions, the `_ALIASES` mapping for shorthand names, and the `SUPPORTED_PROVIDERS` tuple that chapter CLIs import to populate their `--provider` choices.

### How do I add a custom provider alias?

To add a custom alias, modify the `_ALIASES` dictionary in [`agentbook/providers/registry.py`](https://github.com/bojieli/ai-agent-book/blob/main/agentbook/providers/registry.py) by mapping your preferred shorthand to an existing canonical provider key. For example, adding `"custom": "openrouter"` would allow `--provider custom` to resolve to the OpenRouter configuration. No CLI code changes are required.

### What happens if I pass an invalid provider name?

If you pass a provider name not present in `SUPPORTED_PROVIDERS`, `argparse` raises an error immediately during command-line parsing, displaying the valid choices. This validation occurs before any network connections or API calls are attempted.

### Can different chapters use different default providers?

Yes. While all chapters import from the same registry, individual CLIs can implement logic to override the default provider based on chapter-specific requirements. However, the `--provider` flag is available uniformly across chapters, allowing you to override any default by explicitly specifying the desired backend when invoking the script.