How to Configure LLM API Keys and Model Settings for Each Agent in `.env`
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.
| 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
How Settings Are Loaded
The Settings class in 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.
# 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 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, 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:
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):
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:
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):
REPORT_ENGINE_API_KEY=your-gemini-key
REPORT_ENGINE_MODEL_NAME=gemini-2.5-pro
Other Agents
- MindSpider: Uses
MINDSPIDER_API_KEY(defaults todeepseek-chat) - Forum-Host: Uses
FORUM_HOST_API_KEY(defaults toQwen/Qwen3-235B-A22B-Instruct-2507) - Keyword Optimizer: Uses
KEYWORD_OPTIMIZER_API_KEY(defaults toQwen/Qwen3-30B-A3B-Instruct-2507)
Step-by-Step Configuration Guide
-
Copy the template
cp .env.example .env -
Edit
.envand paste the API keys you obtained from each provider (Moonshot, Gemini, DeepSeek, Tavily, etc.). -
Optionally override base URLs or model names if you use custom proxies or different model versions.
-
Verify the settings load correctly:
from config import Settings print(Settings().dict()) -
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_KEYorTAVILY_API_KEY) are missing, as shown inSingleEngineApp/query_engine_streamlit_app.pylines 98-102.
Code Examples
Minimal Local Development Setup
# .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
# .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
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
.envfile. - 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.pyfile 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,MediaEngine/utils/config.py, etc.) re-export these settings for modular imports. - Always copy
.env.exampleto.envand populate the API keys for the agents you intend to use; optional variables likeTAVILY_API_KEYare 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).
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 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 defines the schema with type hints and default values, serving as the source of truth for valid configuration options.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →