How the Agent Reach Config Class Prioritizes Config Files Over Environment Variables
The Agent Reach Config class resolves every setting by first checking the YAML configuration file, then falling back to environment variables, and finally returning an optional default value.
The Config class in the Panniantong/Agent-Reach repository serves as the single source of truth for all user-defined settings. According to the source code in agent_reach/config.py, the Agent Reach Config class prioritizes config files over environment variables by enforcing a strict three-layer lookup hierarchy. This design ensures that persistent YAML-based configuration always masks identically-named environment variables unless the file entry is removed.
Configuration Precedence Hierarchy
The Config class defines an explicit lookup order inside agent_reach/config.py. When you request a key, the resolution follows this sequence:
- Configuration file — Values loaded from
~/.agent-reach/config.yamlinto the internal dictionaryself.data. - Environment variables — If the key is absent from
self.data, the class searchesos.environfor an upper-cased version of the key. - Default argument — If neither source yields a value, the
defaultparameter passed toget()is returned.
Because the file dictionary is checked first with if key in self.data:, any entry stored in the YAML file overrides a matching environment variable automatically.
Loading and Storing File Configuration
On instantiation, the Config class calls its load() method (lines 40–46 of agent_reach/config.py) to read ~/.agent-reach/config.yaml — or a custom path if provided — into the internal self.data dictionary. This dictionary becomes the primary lookup table for all subsequent get() requests.
If the file does not exist or is empty, self.data starts as an empty dictionary, causing the class to skip directly to environment variable resolution.
The get() Method Implementation
The precedence logic lives in the get() method (lines 68–77 of agent_reach/config.py). The implementation performs the following checks in order:
- It first tests whether the requested key exists in
self.data. - If not found, it queries
os.environ.get(key.upper()). - If still unresolved, it returns the user-supplied
default.
This design lets users persist credentials and other settings safely in the local YAML file while still supporting temporary overrides via environment variables whenever the file entry is missing.
Modifying and Persisting Settings
The class exposes several helper methods that operate on the same internal dictionary and persist changes back to disk:
set(key, value)— Updatesself.dataand triggerssave().delete(key)— Removes a key fromself.dataand persists the change.is_configured()— Checks whether the configuration has been populated.get_configured_features()— Returns a list of configured feature keys.
All mutations are written immediately to ~/.agent-reach/config.yaml via the save() method, ensuring the file remains the authoritative source.
Practical Code Examples
The following examples demonstrate the precedence behavior in practice:
from agent_reach.config import Config
import os
# -------------------------------------------------
# Example 1 – Normal lookup (file takes priority)
# -------------------------------------------------
# Assume ~/.agent-reach/config.yaml contains:
# exa_api_key: "file-key-123"
cfg = Config()
print(cfg.get("exa_api_key")) # -> "file-key-123"
# Even if an env var is set, the file value wins
os.environ["EXA_API_KEY"] = "env-key-456"
print(cfg.get("exa_api_key")) # still -> "file-key-123"
# -------------------------------------------------
# Example 2 – Fallback to environment variable
# -------------------------------------------------
# Remove the key from the config file (or use a fresh Config instance)
cfg.delete("exa_api_key")
print(cfg.get("exa_api_key")) # -> "env-key-456"
# -------------------------------------------------
# Example 3 – Providing a default value
# -------------------------------------------------
print(cfg.get("nonexistent_key", default="default-value"))
# -> "default-value"
Summary
- The
Configclass inagent_reach/config.pyenforces a fixed precedence: config file > environment variable > default. - The
load()method populatesself.datafrom~/.agent-reach/config.yamlat instantiation. - The
get()method (lines 68–77) checksself.databefore queryingos.environ.get(key.upper()). - Any key present in the YAML file automatically masks an identically-named environment variable.
- Mutations through
set()anddelete()are persisted back to the YAML file viasave().
Frequently Asked Questions
What happens if a key exists in both the config file and an environment variable?
The file entry always wins. Because agent_reach/config.py checks if key in self.data: before querying os.environ, a value stored in ~/.agent-reach/config.yaml completely overrides its environment counterpart.
How does Agent Reach normalize environment variable names?
The get() method upper-cases the requested key when falling back to environment variables. A lookup for exa_api_key becomes a search for EXA_API_KEY in os.environ.
Can I override a file-based setting temporarily without editing the YAML?
No, not through the standard get() path. Since the file takes priority, you must either delete the key from the config file using cfg.delete(key) or modify the YAML directly so that the environment variable is consulted instead.
Where does Agent Reach store configuration data by default?
By default, the Config class reads from and writes to ~/.agent-reach/config.yaml in the user's home directory. This path is loaded during load() at instantiation and updated on every save() call.
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 →