# Environment Variables That Control Research Behavior and LLM Configuration in local-deep-research

> Discover the LDR_ environment variables that control local-deep-research behavior and LLM configuration. Customize API binding, search, rate limiting, and LLM provider settings easily.

- Repository: [learningcircuit/local-deep-research](https://github.com/learningcircuit/local-deep-research)
- Tags: how-to-guide
- Published: 2026-03-05

---

**The local-deep-research application reads all configuration from environment variables prefixed with `LDR_`, converting dot-notation settings to uppercase underscore format (e.g., `app.host` becomes `LDR_APP_HOST`) to control API binding, search parameters, rate limiting, and LLM provider selection without code changes.**

All runtime behavior in the `learningcircuit/local-deep-research` repository is externally configurable through a unified environment variable system. These variables control the Flask web API bootstrap process, research workflow features like search timeouts and result limits, and detailed LLM client parameters including provider credentials, model selection, and inference tuning. Understanding the `LDR_` prefix convention and the type coercion system allows operators to deploy the application across development, CI, and production environments with zero configuration file edits.

## The LDR_ Prefix and Dot-Notation Conversion

Every environment variable recognized by the system must begin with the **`LDR_`** prefix. The application automatically transforms dot-notation configuration keys into standard environment variable names by replacing periods with underscores and converting to uppercase.

In [`src/local_deep_research/settings/manager.py`](https://github.com/learningcircuit/local-deep-research/blob/main/src/local_deep_research/settings/manager.py), the conversion logic is implemented as:

```python
env_variable_name = f"LDR_{'_'.join(key.split('.')).upper()}"

```

This means a setting key like `llm.temperature` maps to `LDR_LLM_TEMPERATURE`, and `app.port` becomes `LDR_APP_PORT`. The `SettingsManager` class handles this resolution automatically, ensuring environment variables override database defaults and JSON configuration files.

## Bootstrap and General Research Variables

Before the application establishes any database connection, it resolves bootstrap variables via `SettingsManager.get_bootstrap_env_vars()`. These control server binding, security policies, and feature toggles.

### Server and Application Control

- **`LDR_APP_HOST`** – Hostname the Flask API binds to (default: `0.0.0.0`)
- **`LDR_APP_PORT`** – TCP port for the API listener (default: `8000`)
- **`LDR_APP_DEBUG`** – Enables Flask debug mode (`true` or `false`)
- **`LDR_APP_ALLOW_REGISTRATIONS`** – Controls whether new users may register
- **`LDR_DATA_DIR`** – Filesystem path for cache storage and embeddings (e.g., `/var/ldr/data`)
- **`LDR_BOOTSTRAP_ALLOW_UNENCRYPTED`** – Allows startup with an unencrypted database, primarily used in test suites

### Provider and Feature Toggles

- **`LDR_DISABLE_OLLAMA`** – Prevents loading the Ollama provider even if installed
- **`LDR_DISABLE_OPENAI`** – Prevents loading the OpenAI provider
- **`LDR_DISABLE_ANTHROPIC`** – Prevents loading the Anthropic provider
- **`LDR_USE_FALLBACK_LLM`** – Forces the fallback local LLM when remote providers fail
- **`LDR_RATE_LIMITING_ENABLED`** – Activates the global request-rate limiter
- **`LDR_CI`** – Marks CI environment context, disabling interactive prompts (automatically set by CI pipelines)

### Search Behavior Tuning

- **`LDR_SEARCH_TIMEOUT`** – Maximum seconds allowed for a search request (e.g., `30`)
- **`LDR_SEARCH_TOOL_MAX_RESULTS`** – Hard upper bound on search results returned (e.g., `10`)

## LLM Configuration Variables

All LLM-related variables use the **`LDR_LLM_`** prefix and map directly to the `LLMProvider` class initialization parameters. These are processed by the type conversion system defined in `UI_ELEMENT_TO_SETTING_TYPE` (lines 54-61 of manager.py), which coerces string values to booleans, integers, floats, or JSON objects as appropriate.

### Provider Selection and Model Parameters

- **`LDR_LLM_PROVIDER`** – Provider identifier (`openai`, `anthropic`, `ollama`, `gemini`, `localhost`)
- **`LDR_LLM_MODEL`** – Model name for the selected provider (e.g., `gpt-4o`, `llama3.1`)
- **`LDR_LLM_TEMPERATURE`** – Sampling temperature as float (e.g., `0.7`)
- **`LDR_LLM_MAX_TOKENS`** – Token limit for completions (e.g., `2048`)
- **`LDR_LLM_TOP_P`** – Nucleus sampling probability (e.g., `0.9`)
- **`LDR_LLM_N`** – Number of completions to generate
- **`LDR_LLM_LOGPROBS`** – Number of log-probabilities to return
- **`LDR_LLM_TIMEOUT`** – Request timeout in seconds for LLM calls (e.g., `60`)

### Provider-Specific Credentials and Endpoints

- **`LDR_LLM_OPENAI_API_KEY`** – OpenAI API secret
- **`LDR_LLM_ANTHROPIC_API_KEY`** – Anthropic API secret
- **`LDR_LLM_OLLAMA_URL`** – Base URL for Ollama server (e.g., `http://localhost:11434`)
- **`LDR_LLM_OLLAMA_MODEL`** – Specific Ollama model identifier
- **`LDR_LLM_OPENAI_ENDPOINT_URL`** – Custom OpenAI-compatible endpoint (e.g., Azure)
- **`LDR_LLM_OPENAI_ENDPOINT_API_KEY`** – API key for custom endpoints
- **`LDR_LLM_GEMINI_API_KEY`** – Google Gemini API key
- **`LDR_LLM_GEMINI_MODEL`** – Gemini model name (e.g., `gemini-1.5-pro`)
- **`LDR_LLM_GEMINI_ENDPOINT_URL`** – Optional custom Gemini API endpoint

## How Variables Are Resolved

The resolution process occurs in three distinct phases:

1. **Bootstrap Stage** – `SettingsManager.get_bootstrap_env_vars()` extracts critical variables like `LDR_APP_HOST` and `LDR_DATA_DIR` before any database connection is attempted.

2. **General Look-up** – The `check_env_setting(key)` helper constructs the environment variable name using the `LDR_` prefix pattern and calls `os.getenv()`. If present, the environment value overrides database and JSON defaults.

3. **Type Coercion** – The system references the `UI_ELEMENT_TO_SETTING_TYPE` mapping to convert raw strings into appropriate Python types, ensuring `LDR_APP_DEBUG=true` becomes a boolean `True` and `LDR_LLM_TEMPERATURE=0.7` becomes a float.

## Practical Configuration Examples

### Running with OpenAI GPT-4o-mini

Configure the server to use OpenAI with specific model parameters:

```bash
export LDR_APP_HOST=0.0.0.0
export LDR_APP_PORT=8080
export LDR_LLM_PROVIDER=openai
export LDR_LLM_MODEL=gpt-4o-mini
export LDR_LLM_TEMPERATURE=0.5
export LDR_LLM_OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx

docker run -e LDR_APP_HOST -e LDR_APP_PORT -e LDR_LLM_PROVIDER \
           -e LDR_LLM_MODEL -e LDR_LLM_TEMPERATURE -e LDR_LLM_OPENAI_API_KEY \
           learningcircuit/local-deep-research

```

### CI Environment Optimization

Disable external providers and force fallback for faster unit tests:

```bash
export LDR_DISABLE_OPENAI=true
export LDR_DISABLE_OLLAMA=true
export LDR_DISABLE_ANTHROPIC=true
export LDR_USE_FALLBACK_LLM=true
export LDR_CI=true

```

### Custom Search Constraints

Limit search duration and result volume for resource-constrained environments:

```bash
export LDR_SEARCH_TIMEOUT=15
export LDR_SEARCH_TOOL_MAX_RESULTS=5

```

### Local Ollama Integration

Point to a local Ollama instance instead of cloud providers:

```bash
export LDR_LLM_PROVIDER=ollama
export LDR_LLM_OLLAMA_URL=http://localhost:11434
export LDR_LLM_OLLAMA_MODEL=llama3.1

```

## Key Source Files

The environment variable system is implemented across several critical modules:

- **[`src/local_deep_research/settings/manager.py`](https://github.com/learningcircuit/local-deep-research/blob/main/src/local_deep_research/settings/manager.py)** – Contains `SettingsManager` class, the prefix building logic (`env_variable_name = f"LDR_{'_'.join(key.split('.')).upper()}"` on lines 41-44), and the `UI_ELEMENT_TO_SETTING_TYPE` mapping (lines 54-61) for type conversion.

- **[`src/local_deep_research/settings/env_registry.py`](https://github.com/learningcircuit/local-deep-research/blob/main/src/local_deep_research/settings/env_registry.py)** – Central registry listing bootstrap variables and credentials that must remain environment-only.

- **[`src/local_deep_research/web/app_factory.py`](https://github.com/learningcircuit/local-deep-research/blob/main/src/local_deep_research/web/app_factory.py)** – Consumes bootstrap variables to configure Flask debug mode, rate limiting, and server binding.

- **[`src/local_deep_research/web/services/research_service.py`](https://github.com/learningcircuit/local-deep-research/blob/main/src/local_deep_research/web/services/research_service.py)** – Reads LLM configuration variables to initialize provider clients and pass parameters to the inference layer.

- **[`examples/optimization/run_optimization.py`](https://github.com/learningcircuit/local-deep-research/blob/main/examples/optimization/run_optimization.py)** – Demonstrates production deployment patterns setting multiple `LDR_LLM_*` variables programmatically.

## Summary

- All configuration uses the **`LDR_`** prefix with dot-notation keys converted to uppercase underscores (e.g., `llm.model` → `LDR_LLM_MODEL`).
- **Bootstrap variables** like `LDR_APP_HOST`, `LDR_DATA_DIR`, and `LDR_CI` are resolved before database initialization via `SettingsManager.get_bootstrap_env_vars()`.
- **Research behavior** is controlled by `LDR_SEARCH_TIMEOUT`, `LDR_SEARCH_TOOL_MAX_RESULTS`, `LDR_RATE_LIMITING_ENABLED`, and provider disable flags (`LDR_DISABLE_OPENAI`, etc.).
- **LLM configuration** requires `LDR_LLM_PROVIDER` selection plus provider-specific credentials (`LDR_LLM_OPENAI_API_KEY`, `LDR_LLM_OLLAMA_URL`) and inference parameters (`LDR_LLM_TEMPERATURE`, `LDR_LLM_MAX_TOKENS`).
- Type coercion is handled automatically by the `UI_ELEMENT_TO_SETTING_TYPE` mapping in [`manager.py`](https://github.com/learningcircuit/local-deep-research/blob/main/manager.py), converting environment strings to proper Python types.

## Frequently Asked Questions

### How do I change the LLM model without modifying code?

Set the `LDR_LLM_PROVIDER` and `LDR_LLM_MODEL` environment variables. For example, to use OpenAI's GPT-4o, export `LDR_LLM_PROVIDER=openai` and `LDR_LLM_MODEL=gpt-4o` before starting the application. The [`research_service.py`](https://github.com/learningcircuit/local-deep-research/blob/main/research_service.py) module reads these variables to instantiate the correct provider class.

### Why are my boolean environment variables not working?

The system uses the `UI_ELEMENT_TO_SETTING_TYPE` mapping in [`manager.py`](https://github.com/learningcircuit/local-deep-research/blob/main/manager.py) to coerce types. Ensure you use lowercase `true` or `false` for boolean flags like `LDR_APP_DEBUG` or `LDR_RATE_LIMITING_ENABLED`. The conversion logic handles the string-to-boolean transformation automatically.

### Can I use a custom OpenAI-compatible endpoint like Azure?

Yes. Instead of setting `LDR_LLM_OPENAI_API_KEY`, use `LDR_LLM_OPENAI_ENDPOINT_URL` for the base URL (e.g., `https://my-endpoint.openai.azure.com/v1`) and `LDR_LLM_OPENAI_ENDPOINT_API_KEY` for the authentication key. This bypasses the standard OpenAI API configuration and points the client to your custom endpoint.

### What happens if I set `LDR_CI=true`?

Setting `LDR_CI=true` signals to the application that it is running in a continuous integration environment. This disables interactive prompts that would otherwise block execution, allows the `LDR_BOOTSTRAP_ALLOW_UNENCRYPTED` flag to function for test databases, and ensures the application exits cleanly without waiting for user input during initialization.