Three Configuration Layers and Why They're Separate

+15 Mana ✨

Introduction

A naive configuration system has one file: config.json (or config.yaml) and everything lives in it. Hermes deliberately rejects that design. It splits configuration across three files, each with a single job. .env holds secrets. config.yaml holds non-secret settings. SOUL.md holds the agent's identity. The separation looks fussy until you live with the alternative: a single config file that mixes secrets you cannot commit, settings you want in version control, and prose you want to edit by hand.

Key Concepts

  • .env: Secrets only. API keys, bot tokens, passwords. Auto-redacted in logs.
  • config.yaml: Declarative non-secret settings. Model defaults, terminal backend, toolsets, memory limits, display preferences.
  • SOUL.md: Agent identity. The system-prompt slot that defines who the agent is and how it behaves.
  • Each file has a single job: Secrets, settings, identity. Three boxes, no overlap.

Real World Context

A developer wants to share their Hermes config with a teammate so the new hire can reach the same agent setup quickly. With a monolithic config, the developer would have to manually scrub keys before sharing. With three-layer separation, they share config.yaml and SOUL.md directly, the teammate adds their own .env, and the setup is reproducible without exposing any secret. The split was not pedantry; it was preparing for a real moment.

Deep Dive

The layout under ~/.hermes/ looks like this:

text
~/.hermes/
├── .env                # secrets (gitignored, auto-redacted from logs)
├── config.yaml         # settings (shareable, reproducible)
├── SOUL.md             # agent identity (hand-edited prose)
├── auth.json           # OAuth credentials (auto-managed)
├── memories/           # persistent memory entries
├── skills/             # installed skill bundles
├── sessions/           # session history
└── logs/               # error and gateway logs

The three layers each have a job that the others should never do:

.env holds anything that must be secret. API keys (ANTHROPIC_API_KEY=...), bot tokens (TELEGRAM_BOT_TOKEN=...), passwords. Hermes treats this file specially: values from .env are auto-redacted in logs and tool outputs, the file is excluded from any default backup or share, and the structure is just KEY=value lines (no nested YAML).

config.yaml holds anything that defines the runtime but is not a secret. Default model and provider, terminal backend (local, docker), compression strategy, memory limits, toolset enablement, display preferences. It is normal YAML and meant to be read, edited, and version-controlled.

SOUL.md holds the agent's identity. It is Markdown prose, not config syntax. It defines the persona that the agent loads as its primary system prompt: tone, role, default behaviors, things it should always or never do. SOUL.md is deep-dived in a later course; for now, treat it as a third file that exists for a reason.

A pretend overlap (settings inside .env, secrets inside config.yaml) would seem to work but would break specific things. Logs would leak keys. Config would not be shareable. SOUL.md would mix configuration with prose. The three-file split is the simplest design that does not break any of those.

Common Pitfalls

  1. Storing API keys in config.yaml: They will appear in logs, in shared configs, in backups. Use .env.
  2. Editing SOUL.md to add a model setting: SOUL.md is for identity, not configuration. Settings go in config.yaml.

Best Practices

  1. When you add a setting, ask: secret, setting, or identity?: That single question routes it to the right file.
  2. Gitignore .env and version-control config.yaml + SOUL.md: This is the canonical setup for personal Hermes installs.

Summary

  • Hermes splits configuration across three files: .env, config.yaml, SOUL.md.
  • Each file has a single job: secrets, settings, identity.
  • The split prevents leaking secrets in shared configs and logs.
  • The mental model: ask "secret, setting, or identity?" for every new value.

Code Examples

bash
# Three files, three jobs

# Secrets: API keys, bot tokens, passwords
cat ~/.hermes/.env
# ANTHROPIC_API_KEY=sk-ant-...
# OPENROUTER_API_KEY=sk-or-...
# TELEGRAM_BOT_TOKEN=12345:AAH...

# Settings: model defaults, terminal backend, toolsets, memory
cat ~/.hermes/config.yaml
# model: anthropic/claude-sonnet-4-20250514
# terminal:
#   backend: docker
# memory:
#   max_tokens: 200000

# Identity: who the agent is
cat ~/.hermes/SOUL.md
# # SOUL
# You are a focused coding companion. You prefer terse explanations,
# show file paths with line numbers, and never apologize for being wrong.
✓ Completed