How Environment Variables Configure LLM Providers and API Keys in the Hiring Agent

The hiring-agent application reads LLM_PROVIDER, DEFAULT_MODEL, and GEMINI_API_KEY from environment variables to dynamically select between Ollama and Gemini backends without code changes.

The interviewstreet/hiring-agent repository uses a flexible configuration system that leverages environment variables to manage LLM provider selection and authentication. By externalizing provider settings into a .env file, the application enables developers to switch between local models via Ollama and cloud-based Google Gemini APIs simply by adjusting runtime variables. This approach eliminates hard-coded credentials and supports seamless deployment across development, staging, and production environments.

Loading Configuration from Environment Files

In prompt.py, the application initializes its configuration layer by calling python-dotenv's load_dotenv() function, which imports values from a local .env file into the process environment. After loading, the code accesses specific variables using os.getenv() with sensible defaults to ensure the application remains functional even when certain variables are undefined.

Core Environment Variables

The system recognizes three primary environment variables that control LLM behavior and authentication.

Selecting the LLM Provider via LLM_PROVIDER

The PROVIDER constant in prompt.py (lines 21-25) reads from the LLM_PROVIDER environment variable, validating it against the ModelProvider enum defined in models.py. If the variable is missing or contains an unrecognized value, the system forces the setting to ModelProvider.OLLAMA, ensuring the application remains operational without explicit configuration.

Configuring the Default Model with DEFAULT_MODEL

The DEFAULT_MODEL constant retrieves its value from the environment variable of the same name (line 20 in prompt.py), falling back to gemma3:4b when unspecified. This default applies when no specific model is requested during provider initialization, making it easy to standardize model usage across different deployment contexts.

Securing API Keys through GEMINI_API_KEY

For Google Gemini integration, the application retrieves the authentication token from GEMINI_API_KEY (line 67 in prompt.py), defaulting to an empty string when absent. This variable is critical for cloud-based inference; without it, the system cannot instantiate a GeminiProvider and will automatically fall back to local Ollama instances.

Runtime Provider Resolution

The llm_utils.py file contains the initialize_llm_provider function, which implements the runtime selection logic using the MODEL_PROVIDER_MAPPING dictionary (line 53) to determine the appropriate provider for a given model name. When the mapping resolves to ModelProvider.GEMINI, the function checks for a non-empty GEMINI_API_KEY; if the key is missing, it logs a warning and instantiates an OllamaProvider instead (lines 54-60), ensuring graceful degradation rather than runtime failures.

Practical Configuration Examples

Developers can configure the system by creating a .env file in the project root:


# .env configuration

LLM_PROVIDER=gemini          # or "ollama"

DEFAULT_MODEL=gemini-2.5-pro
GEMINI_API_KEY=your_gemini_key_here

To initialize the LLM provider in application code:

from prompt import DEFAULT_MODEL, GEMINI_API_KEY
from llm_utils import initialize_llm_provider

# Initialize based on environment-derived settings

llm = initialize_llm_provider(DEFAULT_MODEL)

# Generate a response

response = llm.chat(
    model=DEFAULT_MODEL,
    messages=[{"role": "user", "content": "Explain the difference between Ollama and Gemini"}]
)
print(response)

When the Gemini key is missing, the fallback behavior activates automatically:


# Assuming LLM_PROVIDER=gemini but GEMINI_API_KEY is empty

llm = initialize_llm_provider("gemini-2.5-pro")

# Logs: "⚠️ Gemini API key not found. Falling back to Ollama."

# Returns: OllamaProvider instance

Summary

  • Environment variables drive provider selection without requiring code modifications
  • prompt.py loads configuration via load_dotenv() and validates against the ModelProvider enum
  • Three variables control behavior: LLM_PROVIDER, DEFAULT_MODEL, and GEMINI_API_KEY
  • Graceful fallback to Ollama occurs when Gemini keys are missing or invalid
  • llm_utils.py implements runtime provider instantiation based on environment-derived settings and the MODEL_PROVIDER_MAPPING lookup

Frequently Asked Questions

What happens if I don't set a Gemini API key?

If GEMINI_API_KEY is empty or unset and the provider mapping suggests Gemini, the application logs a warning message and automatically falls back to an OllamaProvider instance. This allows continued operation using local models even when cloud API credentials are unavailable.

Can I use other LLM providers beyond Ollama and Gemini?

The current implementation in models.py defines a ModelProvider enum limited to OLLAMA and GEMINI values. Adding new providers would require extending this enum and implementing corresponding provider classes in llm_utils.py, as the MODEL_PROVIDER_MAPPING dictionary expects these specific enum values.

Where should I store sensitive API keys in production?

While the .env file works for local development, production deployments should inject GEMINI_API_KEY directly through the hosting platform's secret management system or container orchestration environment variables. Never commit credentials to version control, even in private repositories.

How does the application handle invalid provider names?

In prompt.py, the code validates the LLM_PROVIDER value against the ModelProvider enum; any unrecognized or missing value automatically defaults to ModelProvider.OLLAMA. This defensive programming pattern prevents configuration errors from crashing the application and ensures local development remains friction-free.

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 →