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

> Learn how the hiring agent uses environment variables like LLM_PROVIDER and GEMINI_API_KEY to configure LLM providers and API keys. Easily switch between Ollama and Gemini.

- Repository: [HackerRank/hiring-agent](https://github.com/interviewstreet/hiring-agent)
- Tags: how-to-guide
- Published: 2026-07-05

---

**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`](https://github.com/interviewstreet/hiring-agent/blob/main/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`](https://github.com/interviewstreet/hiring-agent/blob/main/prompt.py) (lines 21-25) reads from the `LLM_PROVIDER` environment variable, validating it against the `ModelProvider` enum defined in [`models.py`](https://github.com/interviewstreet/hiring-agent/blob/main/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`](https://github.com/interviewstreet/hiring-agent/blob/main/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`](https://github.com/interviewstreet/hiring-agent/blob/main/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`](https://github.com/interviewstreet/hiring-agent/blob/main/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:

```bash

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

```python
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:

```python

# 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`](https://github.com/interviewstreet/hiring-agent/blob/main/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`](https://github.com/interviewstreet/hiring-agent/blob/main/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`](https://github.com/interviewstreet/hiring-agent/blob/main/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`](https://github.com/interviewstreet/hiring-agent/blob/main/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`](https://github.com/interviewstreet/hiring-agent/blob/main/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.