How to Select Different LLM Providers in Chapter CLIs

The chapter CLIs in bojieli/ai-agent-book obtain their selectable LLM providers from the centralized provider registry in 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 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:


# 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:


# 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 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:

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, 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, 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. 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →