# How to Configure API Keys for Multiple LLM Providers in aisuite

> Learn to configure multi LLM provider API keys in aisuite. Explore the cascading priority system: explicit args, environment variables, and SecretStore for secure, seamless workflows.

- Repository: [Andrew Ng/aisuite](https://github.com/andrewyng/aisuite)
- Tags: how-to-guide
- Published: 2026-07-28

---

**aisuite resolves API keys through a cascading priority system: explicit arguments first, then environment variables, then SecretStore entries, allowing seamless multi-provider workflows without hardcoded secrets.**

The `aisuite` library from the `andrewyng/aisuite` repository provides a unified interface for interacting with diverse large language model (LLM) providers. To configure API keys for multiple LLM providers in aisuite, you leverage a hierarchical resolution system that prioritizes security and flexibility. Each provider implements a resolver function that searches for credentials in three distinct layers before making API calls.

## Understanding the API Key Resolution Hierarchy

Every provider in aisuite follows a standardized credential lookup pattern implemented in resolver functions. The resolution order is:

1. **Explicit argument** passed directly to the provider configuration (`api_key="sk-..."`)
2. **Environment variable** specific to each provider (e.g., `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`)
3. **SecretStore entry** under the `provider:<name>` profile, typically managed through the Settings UI

This design ensures that sensitive credentials never need to be hardcoded in source files while supporting dynamic configuration across development and production environments.

## Provider-Specific Configuration Sources

### OpenAI Provider Configuration

In [`platform/coworker/providers/openai_provider.py`](https://github.com/andrewyng/aisuite/blob/main/platform/coworker/providers/openai_provider.py), the `resolve_api_key` function (lines 23-38) first checks for an explicitly passed API key, then falls back to the `OPENAI_API_KEY` environment variable, and finally queries the SecretStore for `provider:openai` according to the andrewyng/aisuite source code.

### Anthropic Provider Configuration

The Anthropic resolver in [`platform/coworker/providers/anthropic_provider.py`](https://github.com/andrewyng/aisuite/blob/main/platform/coworker/providers/anthropic_provider.py) (lines 62-75) searches for `ANTHROPIC_API_KEY` in the environment before checking `secrets.get("provider:anthropic")` as implemented in andrewyng/aisuite.

### Gemini Provider Configuration

For Google's Gemini, [`platform/coworker/providers/gemini_provider.py`](https://github.com/andrewyng/aisuite/blob/main/platform/coworker/providers/gemini_provider.py) (lines 81-92) implements a dual environment variable check: it prefers `GEMINI_API_KEY` but accepts `GOOGLE_API_KEY` as a fallback before resorting to the SecretStore entry `provider:gemini`.

## Initializing the Client with Multiple Providers

The `Client` class in [`aisuite/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/client.py) manages provider configurations through the `provider_configs` parameter. When you instantiate the client with `Client(provider_configs={...})` or call `client.configure(...)`, aisuite stores these configurations and lazily initializes provider instances via `Client._resolve_provider` (lines 52-74 and 99-104).

Each provider entry in the configuration dictionary supports an `api_key` field. When set to `None`, aisuite triggers the resolver chain to locate credentials automatically from environment variables or the SecretStore.

## Practical Multi-Provider Setup

Create a `.env` file in your project root using the variables defined in `.env.sample` (which lists all supported variables for OpenAI, Anthropic, Gemini, Azure, AWS, and others), then load it automatically via `python-dotenv`:

```python
import aisuite as ai

# Create a client capable of routing to multiple providers

client = ai.Client(
    provider_configs={
        "openai": {"api_key": None},      # Resolves via OPENAI_API_KEY

        "anthropic": {"api_key": None},   # Resolves via ANTHROPIC_API_KEY

        "gemini": {"api_key": None},      # Resolves via GEMINI_API_KEY

    }
)

# Route to OpenAI

response = client.chat.completions.create(
    model="openai:gpt-4-turbo",
    messages=[{"role": "user", "content": "Explain polymorphism."}]
)
print(f"OpenAI: {response.choices[0].message.content}")

# Route to Anthropic

response = client.chat.completions.create(
    model="anthropic:claude-3-sonnet-20240229",
    messages=[{"role": "user", "content": "Explain inheritance."}]
)
print(f"Anthropic: {response.choices[0].message.content}")

# Route to Gemini

response = client.chat.completions.create(
    model="gemini:gemini-1.5-flash",
    messages=[{"role": "user", "content": "Explain encapsulation."}]
)
print(f"Gemini: {response.choices[0].message.content}")

```

Each request automatically resolves the appropriate API key based on the provider prefix in the model identifier (e.g., `"openai:"`, `"anthropic:"`, `"gemini:"`).

## Summary

- **aisuite uses a three-tier resolution system**: explicit arguments override environment variables, which override SecretStore entries.
- **Provider resolvers live in** `platform/coworker/providers/` with each module implementing a `resolve_api_key` function following the pattern established in [`openai_provider.py`](https://github.com/andrewyng/aisuite/blob/main/openai_provider.py), [`anthropic_provider.py`](https://github.com/andrewyng/aisuite/blob/main/anthropic_provider.py), and [`gemini_provider.py`](https://github.com/andrewyng/aisuite/blob/main/gemini_provider.py).
- **Environment variables follow naming conventions**: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, and `GEMINI_API_KEY` (or `GOOGLE_API_KEY` as fallback).
- **The `Client` class** in [`aisuite/client.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/client.py) lazily initializes providers and triggers key resolution via `Client._resolve_provider`.
- **Reference `.env.sample`** for the complete list of supported environment variables across all integrated platforms.

## Frequently Asked Questions

### What is the exact priority order for API key resolution in aisuite?

aisuite checks credentials in the following strict order: first, any explicit `api_key` argument passed in the provider configuration; second, the provider-specific environment variable (such as `OPENAI_API_KEY`); third, the SecretStore entry under the `provider:<name>` profile. This hierarchy ensures maximum flexibility while preventing accidental credential leakage in version control.

### Can I mix explicit API keys and environment variables for different providers?

Yes. The `provider_configs` dictionary accepts `None` for providers that should resolve via environment variables or SecretStore, while simultaneously accepting explicit strings for other providers. This allows you to hardcode keys for experimental providers while keeping production credentials in environment variables.

### How does aisuite handle the Gemini API key versus the Google API key?

According to the source in [`platform/coworker/providers/gemini_provider.py`](https://github.com/andrewyng/aisuite/blob/main/platform/coworker/providers/gemini_provider.py), the resolver prefers `GEMINI_API_KEY` but automatically falls back to `GOOGLE_API_KEY` if the primary variable is unset. This dual-check pattern accommodates users migrating from the older Google AI SDK to the newer Gemini-specific endpoints.

### Where should I store API keys for the aisuite Settings UI to find them?

When using the graphical Settings interface, keys are stored in the internal SecretStore under the profile key `provider:<name>` (e.g., `provider:openai`, `provider:anthropic`). These entries are checked last in the resolution chain and provide a secure alternative to environment variables for desktop applications.