# How to Configure LLM API Keys and Model Settings for Each Agent in `.env`

> Configure LLM API keys and model settings for each agent in your .env file with BettaFish. Easily manage diverse provider configurations for agents without code changes.

- Repository: [BaiFu/bettafish](https://github.com/666ghj/bettafish)
- Tags: how-to-guide
- Published: 2026-02-23

---

**BettaFish reads all LLM credentials and model configurations from a single `.env` file using Pydantic-Settings, allowing each agent to use different providers without modifying source code.**

BettaFish is a multi-agent research automation framework where each engine (Insight, Media, Query, Report, etc.) can connect to different LLM providers. Rather than hardcoding credentials, the project centralizes configuration through environment variables. This guide explains exactly which variables to set and how the system loads them.

## What the `.env` File Contains

The project includes an **`.env.example`** template that documents every available variable. All entries are optional; missing values fall back to hardcoded defaults in [`config.py`](https://github.com/666ghj/bettafish/blob/main/config.py).

| Variable | Purpose | Default (if omitted) |
|----------|---------|-----------------------|
| `INSIGHT_ENGINE_API_KEY` | API key for the Insight LLM | *none* |
| `MEDIA_ENGINE_API_KEY` | API key for the Media LLM | *none* |
| `QUERY_ENGINE_API_KEY` | API key for the Query LLM | *none* |
| `REPORT_ENGINE_API_KEY` | API key for the Report LLM | *none* |
| `MINDSPIDER_API_KEY` | API key for the MindSpider agent | *none* |
| `FORUM_HOST_API_KEY` | API key for the Forum-Host agent | *none* |
| `KEYWORD_OPTIMIZER_API_KEY` | API key for the Keyword Optimizer | *none* |
| `TAVILY_API_KEY` | API key for Tavily web-search (required by Query engine) | *none* |
| `BOCHA_WEB_SEARCH_API_KEY` | API key for Bocha web-search (optional, used by Media engine) | *none* |
| `ANSPIRE_API_KEY` | API key for Anspire AI search (optional, used by Media engine) | *none* |
| `*_BASE_URL` | Override the HTTP endpoint for any provider | Provider-specific default |
| `*_MODEL_NAME` | Explicitly set the model name for any provider | Provider-specific default |

Source: [`.env.example` lines 29-77](https://github.com/666ghj/bettafish/blob/main/.env.example#L29)

## How Settings Are Loaded

The **`Settings`** class in [`config.py`](https://github.com/666ghj/bettafish/blob/main/config.py) declares every field using `pydantic.Field`. When instantiated, Pydantic reads environment variables from the current working directory's `.env` first, then falls back to the project root's `.env`.

```python

# config.py – excerpt

class Settings(BaseSettings):
    INSIGHT_ENGINE_API_KEY: Optional[str] = Field(
        None,
        description="Insight Agent API key"
    )
    INSIGHT_ENGINE_BASE_URL: Optional[str] = Field(
        "https://api.moonshot.cn/v1",
        description="Insight Agent LLM BaseUrl"
    )
    INSIGHT_ENGINE_MODEL_NAME: str = Field(
        "kimi-k2-0711-preview",
        description="Insight Agent LLM model name"
    )
    # ... (similar fields for Media, Query, Report, etc.)

    
    class Config:
        env_file = ".env"

```

Source: [[`config.py`](https://github.com/666ghj/bettafish/blob/main/config.py) lines 45-53](https://github.com/666ghj/bettafish/blob/main/config.py#L45)

Each engine also ships its own tiny config module (e.g., [`MediaEngine/utils/config.py`](https://github.com/666ghj/bettafish/blob/main/MediaEngine/utils/config.py), [`QueryEngine/utils/config.py`](https://github.com/666ghj/bettafish/blob/main/QueryEngine/utils/config.py)) that re-exports the same fields, allowing sub-packages to import their own `Settings` without importing the entire codebase.

## Configuring Individual Agents

### Insight Engine

The Insight engine defaults to **Moonshot AI** (`kimi-k2-0711-preview`). Set these variables:

```dotenv
INSIGHT_ENGINE_API_KEY=sk-your-moonshot-key
INSIGHT_ENGINE_BASE_URL=https://api.moonshot.cn/v1
INSIGHT_ENGINE_MODEL_NAME=kimi-k2-0711-preview

```

### Media Engine

The Media engine defaults to **Gemini** (`gemini-2.5-pro`):

```dotenv
MEDIA_ENGINE_API_KEY=your-gemini-key
MEDIA_ENGINE_MODEL_NAME=gemini-2.5-pro

```

### Query Engine

The Query engine defaults to **DeepSeek** (`deepseek-chat`) and **requires** a Tavily key for web search:

```dotenv
QUERY_ENGINE_API_KEY=sk-your-deepseek-key
QUERY_ENGINE_MODEL_NAME=deepseek-chat
TAVILY_API_KEY=tvly-your-tavily-key

```

### Report Engine

The Report engine also defaults to **Gemini** (`gemini-2.5-pro`):

```dotenv
REPORT_ENGINE_API_KEY=your-gemini-key
REPORT_ENGINE_MODEL_NAME=gemini-2.5-pro

```

### Other Agents

- **MindSpider**: Uses `MINDSPIDER_API_KEY` (defaults to `deepseek-chat`)
- **Forum-Host**: Uses `FORUM_HOST_API_KEY` (defaults to `Qwen/Qwen3-235B-A22B-Instruct-2507`)
- **Keyword Optimizer**: Uses `KEYWORD_OPTIMIZER_API_KEY` (defaults to `Qwen/Qwen3-30B-A3B-Instruct-2507`)

## Step-by-Step Configuration Guide

1. **Copy the template**
   ```bash
   cp .env.example .env
   ```

2. **Edit `.env`** and paste the API keys you obtained from each provider (Moonshot, Gemini, DeepSeek, Tavily, etc.).

3. **Optionally override** base URLs or model names if you use custom proxies or different model versions.

4. **Verify** the settings load correctly:
   ```python
   from config import Settings
   print(Settings().dict())
   ```

5. **Run the desired engine** – the code automatically reads the values. For Streamlit apps, the UI warns you if required keys (e.g., `QUERY_ENGINE_API_KEY` or `TAVILY_API_KEY`) are missing, as shown in [`SingleEngineApp/query_engine_streamlit_app.py`](https://github.com/666ghj/bettafish/blob/main/SingleEngineApp/query_engine_streamlit_app.py) lines 98-102.

## Code Examples

### Minimal Local Development Setup

```dotenv

# .env

INSIGHT_ENGINE_API_KEY=sk-xxxx-insight
MEDIA_ENGINE_API_KEY=sk-xxxx-media
QUERY_ENGINE_API_KEY=sk-xxxx-query
REPORT_ENGINE_API_KEY=sk-xxxx-report
TAVILY_API_KEY=tvly-xxxx

```

All other variables keep their defaults (base URLs and model names).

### Custom Provider URLs and Models

```dotenv

# .env

QUERY_ENGINE_API_KEY=sk-xxxx-query
QUERY_ENGINE_BASE_URL=https://my-proxy.example.com/v1
QUERY_ENGINE_MODEL_NAME=deepseek-reasoner

```

The Query engine now calls `https://my-proxy.example.com/v1` with the `deepseek-reasoner` model.

### Programmatic Access

```python
from config import Settings

settings = Settings()          # reads .env automatically

print("Insight model:", settings.INSIGHT_ENGINE_MODEL_NAME)
print("Media key set:", bool(settings.MEDIA_ENGINE_API_KEY))

```

## Summary

- BettaFish uses **Pydantic-Settings** to centralize all LLM configuration in a single `.env` file.
- Each agent (Insight, Media, Query, Report, MindSpider, etc.) has dedicated environment variables following the pattern `{AGENT}_API_KEY`, `{AGENT}_BASE_URL`, and `{AGENT}_MODEL_NAME`.
- The [`config.py`](https://github.com/666ghj/bettafish/blob/main/config.py) file defines global defaults (e.g., Insight uses Moonshot, Media uses Gemini), which you can override via environment variables.
- Engine-specific config modules ([`QueryEngine/utils/config.py`](https://github.com/666ghj/bettafish/blob/main/QueryEngine/utils/config.py), [`MediaEngine/utils/config.py`](https://github.com/666ghj/bettafish/blob/main/MediaEngine/utils/config.py), etc.) re-export these settings for modular imports.
- Always copy `.env.example` to `.env` and populate the API keys for the agents you intend to use; optional variables like `TAVILY_API_KEY` are required only for specific engines.

## Frequently Asked Questions

### What happens if I don't set an API key for a specific agent?

If an API key is missing, the Pydantic-Settings loader returns `None` for that field. When the agent attempts to initialize its LLM client, it will either fail with an authentication error or, in the case of Streamlit apps, display a UI warning prompting you to set the missing key (as seen in [`SingleEngineApp/query_engine_streamlit_app.py`](https://github.com/666ghj/bettafish/blob/main/SingleEngineApp/query_engine_streamlit_app.py)).

### Can I use the same LLM provider for multiple agents?

Yes. Simply set the same API key for multiple `*_API_KEY` variables. For example, if you want both the Query and Insight engines to use DeepSeek, set both `QUERY_ENGINE_API_KEY` and `INSIGHT_ENGINE_API_KEY` to your DeepSeek key. You can also override the model names individually if you want different DeepSeek models for each agent.

### How do I configure a custom proxy or self-hosted LLM?

Use the `*_BASE_URL` environment variables. For example, to route the Query engine through a custom proxy, set `QUERY_ENGINE_BASE_URL=https://your-proxy.example.com/v1`. The code in [`config.py`](https://github.com/666ghj/bettafish/blob/main/config.py) uses these variables directly when initializing the OpenAI-compatible clients, allowing you to point to any OpenAI API-compatible endpoint.

### Where can I find the complete list of configurable variables?

The definitive reference is the `.env.example` file in the repository root. It contains every supported variable with inline comments describing their purpose. Additionally, the `Settings` class in [`config.py`](https://github.com/666ghj/bettafish/blob/main/config.py) defines the schema with type hints and default values, serving as the source of truth for valid configuration options.