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

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, the conversion logic is implemented as:

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:

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:

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:

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:

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:

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, 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 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 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.

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 →