Configuration: config.yaml, .env, and Profiles
- Locate every Hermes config file and know what kind of setting belongs in each
- Explain the configuration resolution order: CLI args, config.yaml, .env, then defaults
- Read and modify the core config.yaml sections: model, terminal, memory, compression, agent, tts, display
- Use ${VAR_NAME} environment variable substitution correctly inside config.yaml
- Run an isolated second agent identity using the -p profile flag
- Use hermes config / config edit / config set / config check to manage settings
Where Everything Lives
Everything Hermes needs is stored under ~/.hermes/:
config.yaml-- primary settings: model, terminal behavior, TTS, compression, and more.env-- API keys, secrets, tokens; anything sensitive belongs here, not in config.yamlauth.json-- OAuth provider credentialsSOUL.md-- the agent's identity file (Lesson 5)memories/-- persistent memory files (Lesson 8)skills/-- agent-created and installed skills (Hermes Agent Advanced)sessions/-- gateway session data
How Settings Resolve
When the same setting could come from more than one place, Hermes resolves it in this priority order:
- CLI arguments (override for just this one invocation)
~/.hermes/config.yaml~/.hermes/.env(as a fallback source for environment variables)- Built-in defaults
The rule worth memorizing: secrets go in .env; everything else goes in config.yaml. If you ever find yourself about to paste an API key into config.yaml, stop -- it belongs in .env instead.
The Core Sections of config.yaml
A real config.yaml has several sections you will touch over time. Here is the shape of the important ones:
model:
default: "anthropic/claude-opus-4"
provider: "openrouter"
terminal:
backend: "local" # local | docker | ssh | modal | daytona | singularity
timeout: 180
persistent_shell: true
memory:
memory_enabled: true
memory_char_limit: 2200
compression:
enabled: true
threshold: 0.50
agent:
max_turns: 90
reasoning_effort: "medium"
tool_use_enforcement: "auto"
tts:
provider: "edge"
voice: "en-US-AriaNeural"
display:
tool_progress: "all"
streaming: false
You do not need to understand every field today. The two worth knowing now: compression.threshold: 0.50 means Hermes starts compressing older parts of a long conversation once it hits 50% of the model's context window, and compression.protect_last_n (not shown above, but available) keeps a fixed number of your most recent messages uncompressed so recent context never gets summarized away.
Terminal Backends
The terminal.backend setting controls where commands the agent runs actually execute. local is the default and needs no setup. The others matter once you start running untrusted code or want isolation:
# Docker backend
terminal:
backend: docker
docker_image: "nikolaik/python-nodejs:python3.11-nodejs20"
docker_forward_env:
- "GITHUB_TOKEN"
docker_volumes:
- "/home/user/projects:/workspace/projects"
# SSH backend
terminal:
backend: ssh
persistent_shell: true
Security and sandboxing considerations for these backends are covered properly in Hermes Agent Advanced -- for now, just know local is fine to start with.
Environment Variable Substitution
You can reference values from your environment directly inside config.yaml using ${VAR_NAME} syntax:
auxiliary:
vision:
api_key: ${GOOGLE_API_KEY}
Only the ${VAR} form is supported -- a bare $VAR without braces will not be expanded. This is a small detail that trips people up the first time they try it.
Profiles: Running More Than One Agent
So far everything has assumed one agent. Hermes supports running multiple, fully isolated agent identities on the same machine via the -p flag:
hermes -p work chat
hermes -p research chat
Each named profile gets its own complete set of directories -- separate config, separate memory, separate sessions, separate skills -- under ~/.hermes/profiles/<profile>/. A "work" agent and a "research" agent do not share memory or identity unless you explicitly set that up. This is also the foundation for the special-case agent you will see referenced occasionally in Hermes documentation and community examples: the default profile (no -p flag at all) uses the root ~/.hermes/ directory directly rather than a named subdirectory.
You do not need multiple profiles to get value out of Hermes -- most people start with just the default profile, which is exactly what Lessons 5 through 9 of this track assume. But it is worth knowing the mechanism exists, because Hermes Agent Advanced's coverage of multi-agent delegation and the kanban board builds directly on top of it.
Inspecting and Changing Configuration
hermes config # View current settings
hermes config edit # Open config.yaml in your editor
hermes config set KEY VAL # Set a specific value from the command line
hermes config check # Verify configuration after making changes
hermes config check is worth running any time you hand-edit the YAML file directly -- it catches malformed settings before they cause a confusing runtime error later.
With configuration covered, the next lesson moves to something that actually changes how your agent feels to talk to: giving it an identity with SOUL.md.
- Secrets go in .env, everything else goes in config.yaml -- this split is consistent across all of Hermes, not just a suggestion
- Settings resolve in order: CLI args override config.yaml, which overrides .env, which overrides built-in defaults
- Environment variable substitution only works with the ${VAR} braced form -- bare $VAR is not expanded
- Profiles (-p flag) give each agent identity its own isolated ~/.hermes/profiles/<profile>/ directory for config, memory, sessions, and skills
- The default profile (no -p flag) uses the root ~/.hermes/ directory directly -- this special case comes up again whenever you read about multi-agent setups