# How Agent-Reach's Configuration System Manages YAML Files and Environment Variable Fallbacks

> Learn how Agent-Reach's configuration system uses YAML files and environment variable fallbacks. Discover its priority-based lookup chain for seamless settings management.

- Repository: [Pnant/Agent-Reach](https://github.com/Panniantong/Agent-Reach)
- Tags: how-to-guide
- Published: 2026-07-12

---

**Agent-Reach stores user-specific configuration in `~/.agent-reach/config.yaml` and automatically falls back to uppercase environment variables when YAML keys are missing, using a priority-based lookup chain in the `Config` class.**

The `Panniantong/Agent-Reach` repository implements a secure, dual-source configuration system that prioritizes persistent YAML settings while allowing temporary overrides via environment variables. This architecture lets developers commit default values to version control while keeping secrets and deployment-specific overrides in environment variables. The system is implemented in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) and handles directory creation, file permissions, and cascading lookups automatically.

## Configuration Storage and File Structure

Agent-Reach persists user settings in a dedicated configuration directory that is created with restrictive permissions on first access.

### Secure Directory Creation

When the `Config` class is instantiated, it calls `make_private_dir` from [`agent_reach/utils/paths.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/paths.py) to ensure the `~/.agent-reach/` directory exists. This utility creates the folder with permissions restricted to the owner only, preventing other system users from accessing configuration files that may contain API keys and tokens.

### YAML File Location and Permissions

The configuration file is stored at `~/.agent-reach/config.yaml`. When the `save()` method writes data to disk, it explicitly sets **600-style permissions** (`rw-------`), ensuring that only the file owner can read or write the configuration. This security model is critical for protecting sensitive credentials like `exa_api_key` or `openai_api_key` that users store in the YAML file.

## The Lookup Chain: YAML Precedence with Environment Fallback

The core retrieval logic resides in the `get()` method within [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py). This method implements a three-tier lookup system:

1. **YAML Data**: Check if the key exists in the loaded dictionary from [`config.yaml`](https://github.com/Panniantong/Agent-Reach/blob/main/config.yaml)
2. **Environment Variable**: Convert the key to uppercase and check `os.environ`
3. **Default Value**: Return the user-supplied default if neither source provides a value

```python
def get(self, key: str, default: Any = None) -> Any:
    # 1️⃣  Look in the loaded YAML data

    if key in self.data:
        return self.data[key]
    # 2️⃣  Fallback to an environment variable (uppercase version of the key)

    env_val = os.environ.get(key.upper())
    if env_val:
        return env_val
    # 3️⃣  Return the supplied default if neither source provides a value

    return default

```

This approach means that a setting defined in [`config.yaml`](https://github.com/Panniantong/Agent-Reach/blob/main/config.yaml) takes precedence, but if it is absent, the system automatically checks for an environment variable with the same name converted to uppercase.

## Configuration Management Methods

### Loading and Saving Configuration

The `load()` method reads the YAML file using `yaml.safe_load`. If the file is missing or empty, it initializes an empty dictionary, ensuring the application starts without errors even on fresh installations. The `save()` method persists the in-memory dictionary back to `~/.agent-reach/config.yaml` while maintaining the strict 600 permissions.

### Retrieving Values with Fallbacks

To retrieve a configuration value with automatic fallback to environment variables, instantiate the `Config` class and call `get()`:

```python
from agent_reach.config import Config

cfg = Config()
api_key = cfg.get("exa_api_key", default="none")
print(api_key)      # Uses value from ~/.agent-reach/config.yaml if present,

                    # otherwise falls back to the EXA_API_KEY environment variable.

```

### Setting and Deleting Keys

The `set()` method updates the in-memory configuration and immediately persists it to disk, while `delete()` removes a key from both the dictionary and the YAML file:

```python
cfg.set("openai_api_key", "sk-xxxxxxxxxxxx")

# The key is now stored in ~/.agent-reach/config.yaml with secure file permissions.

cfg.delete("github_token")   # Deletes the key from the in‑memory dict and saves the file.

```

## Feature-Specific Configuration Requirements

Agent-Reach declares feature-specific requirements in a `FEATURE_REQUIREMENTS` dictionary (located in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py)), which maps feature names to lists of required configuration keys. For example, the `exa_search` feature requires an `exa_api_key`.

The `is_configured()` method verifies that **all required keys are available** via the same lookup chain used by `get()`:

```python
if cfg.is_configured("twitter_xreach"):
    print("Twitter integration can be used")
else:
    print("Missing required Twitter credentials")

```

This validation ensures that applications can check readiness before attempting to use external APIs, preventing runtime errors from missing credentials.

## Summary

- **Agent-Reach** stores configuration in `~/.agent-reach/config.yaml` with **600 permissions** (`rw-------`) to protect secrets.
- The `Config` class in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) loads YAML data using `yaml.safe_load` and defaults to an empty dictionary if the file is missing.
- The `get()` method implements a priority chain: YAML values first, then uppercase environment variables, then user-supplied defaults.
- **Feature requirements** are defined in `FEATURE_REQUIREMENTS` and validated via `is_configured()`, which uses the same fallback logic.
- The `make_private_dir` utility in [`agent_reach/utils/paths.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/utils/paths.py) ensures the configuration directory is created with owner-only access.

## Frequently Asked Questions

### How does Agent-Reach prioritize between YAML files and environment variables?

Agent-Reach checks the YAML file first via the `get()` method. If the key is not found in `~/.agent-reach/config.yaml`, it automatically converts the key to uppercase and checks `os.environ`. Only if neither source has the value does it return the user-supplied default. This means YAML settings always take precedence over environment variables.

### What permissions does Agent-Reach set on configuration files?

The configuration directory is created with permissions restricted to the owner only using `make_private_dir`. When saving the YAML file, the `save()` method explicitly sets **600-style permissions** (`rw-------`), ensuring that only the file owner can read or write sensitive configuration data like API keys.

### Can I use Agent-Reach without creating a YAML file?

Yes. If `~/.agent-reach/config.yaml` does not exist, the `load()` method initializes an empty dictionary and the application continues normally. You can rely entirely on environment variables (uppercase versions of your configuration keys) without ever creating the YAML file, making the system suitable for containerized deployments where environment variables are preferred.

### How do I check if a specific feature has all required configuration?

Use the `is_configured()` method, passing the feature name as defined in `FEATURE_REQUIREMENTS`. This method checks that all required keys for that feature are present using the same YAML-to-environment fallback logic. For example, `cfg.is_configured("exa_search")` verifies that `exa_api_key` is available either in the YAML file or as the `EXA_API_KEY` environment variable.