Learn Hermes Agent Fundamentals Configuration: config.yaml, .env, and Profiles

Configuration: config.yaml, .env, and Profiles

Intermediate 🕐 24 min Lesson 4 of 9
What you'll learn
  • 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.yaml
  • auth.json -- OAuth provider credentials
  • SOUL.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:

  1. CLI arguments (override for just this one invocation)
  2. ~/.hermes/config.yaml
  3. ~/.hermes/.env (as a fallback source for environment variables)
  4. 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.

Key takeaways
  • 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