hermes - ✅(Solved) Fix [Bug]: setup wizard double-writes max_turns to both .env (HERMES_MAX_ITERATIONS) and config.yaml (agent.max_turns), causing silent state drift [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#17534Fetched 2026-04-30 06:46:58
View on GitHub
Comments
0
Participants
1
Timeline
7
Reactions
0
Author
Participants
Timeline (top)
labeled ×4cross-referenced ×2referenced ×1

`hermes_cli/setup.py` writes the "Max iterations" wizard answer to two places at once:

```python save_env_value("HERMES_MAX_ITERATIONS", str(max_iter)) # writes ~/.hermes/.env config.setdefault("agent", {})["max_turns"] = max_iter # writes config.yaml ```

Combined with the priority chain in `cli.py:2042-2051` (`config > env`), this creates a silent failure mode: any later edit to only one of the two stores leaves the other as a stale ghost. CLI `hermes config show` reports the config value (`200`), while sessions that load through paths preferring env may show the env value (`300`).

Error Message

  • The error surfaces in long-running sessions resumed from suspended state, where the loaded `max_turns` may differ from the live config.
  1. Drop the env-var path — only write/read `config.yaml`, keeping `HERMES_MAX_ITERATIONS` for legacy install detection only (warn-and-migrate on startup if found).
  2. Or keep dual-write, but on `hermes config show` / `hermes config check` actively diff env vs config.yaml and warn on drift.

Root Cause

`hermes_cli/setup.py` writes the "Max iterations" wizard answer to two places at once:

```python save_env_value("HERMES_MAX_ITERATIONS", str(max_iter)) # writes ~/.hermes/.env config.setdefault("agent", {})["max_turns"] = max_iter # writes config.yaml ```

Combined with the priority chain in `cli.py:2042-2051` (`config > env`), this creates a silent failure mode: any later edit to only one of the two stores leaves the other as a stale ghost. CLI `hermes config show` reports the config value (`200`), while sessions that load through paths preferring env may show the env value (`300`).

Fix Action

Fixed

PR fix notes

PR #17554: fix(setup): keep max turns in config

Description (problem / solution / changelog)

Summary

  • Keeps agent.max_turns as the setup wizard source of truth instead of dual-writing HERMES_MAX_ITERATIONS.
  • Clears the legacy HERMES_MAX_ITERATIONS entry when setup writes max turns, preventing stale env values from shadowing config in env-only paths.
  • Preserves legacy env-only installs by using HERMES_MAX_ITERATIONS as the default only when config has no agent.max_turns.

Root cause

The setup wizard read HERMES_MAX_ITERATIONS before agent.max_turns and wrote updates to both .env and config.yaml. That allowed an old env value to remain as a hidden second source of truth after users edited config only.

Fix

Prefer agent.max_turns in setup defaults and remove HERMES_MAX_ITERATIONS after writing max turns to config.

Regression coverage

  • Added coverage for a stale HERMES_MAX_ITERATIONS not overriding configured agent.max_turns in the setup wizard.
  • Added coverage that legacy env-only configurations still use the env value as their initial default and migrate it into config.

Testing

  • scripts/run_tests.sh tests/hermes_cli/test_setup_agent_settings.py -q
  • scripts/run_tests.sh tests/hermes_cli/test_setup.py::test_vercel_setup_prefills_project_and_team_from_link_file -q
  • scripts/run_tests.sh tests/hermes_cli/test_setup_agent_settings.py tests/hermes_cli/test_setup_reconfigure.py tests/hermes_cli/test_setup_noninteractive.py -q

Closes #17534

Changed files

  • hermes_cli/setup.py (modified, +5/-5)
  • tests/hermes_cli/test_setup_agent_settings.py (modified, +34/-3)

PR #17672: fix(cli): drop max_turns env-var dual-write in setup wizard (#17534)

Description (problem / solution / changelog)

What does this PR do?

The setup wizard was dual-writing the max-iterations value to both .env (HERMES_MAX_ITERATIONS) and config.yaml (agent.max_turns) at the same time, then reading env first when re-prompting. As soon as a user later edited only one store (hermes config set, manual edit, AI-assisted edit), the other store became a stale ghost — hermes config show reported the config value while gateway/Telegram sessions surfaced the env value, leading to silent state drift like iteration 9/300 despite Max turns: 200 in hermes config show.

This PR makes config.yaml the single source of truth in the wizard. The legacy env-var path stays readable as a backwards-compat fallback at the bottom of cli.py's priority chain (no behaviour change for users who haven't run the wizard since this fix), and gateway/run.py continues to bridge agent.max_turns into HERMES_MAX_ITERATIONS at startup so downstream env-only readers stay consistent.

Related Issue

Fixes #17534

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • hermes_cli/setup.py::_apply_default_agent_settings no longer calls save_env_value(\"HERMES_MAX_ITERATIONS\", \"90\") when applying recommended defaults.
  • hermes_cli/setup.py::setup_agent_settings no longer calls save_env_value(\"HERMES_MAX_ITERATIONS\", ...) after the prompt, and reads the current value from config[\"agent\"][\"max_turns\"] instead of preferring HERMES_MAX_ITERATIONS from the environment.
  • tests/hermes_cli/test_setup_agent_settings.py updated and extended:
    • The displayed-helper test now asserts the wizard ignores a stale env value and shows the config value.
    • Two new regression tests assert that neither setup_agent_settings nor _apply_default_agent_settings writes HERMES_MAX_ITERATIONS to .env.

How to Test

  1. With a config containing agent.max_turns: 200, set HERMES_MAX_ITERATIONS=300 in ~/.hermes/.env (simulating a stale ghost from a prior wizard run).
  2. Run `hermes setup agent`. The prompt should display `Press Enter to keep 200.`, not 300.
  3. Set max iterations to a new value (e.g. 250). Confirm:
    • ~/.hermes/config.yaml now has agent.max_turns: 250.
    • ~/.hermes/.env is unchanged (stale HERMES_MAX_ITERATIONS=300 is not rewritten — gateway will overwrite it from config at startup via gateway/run.py:347).
  4. Run the focused tests:
    pytest tests/hermes_cli/test_setup_agent_settings.py -v
    All three tests pass with this fix and fail without it.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (`fix(scope):`, `feat(scope):`, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run `pytest tests/hermes_cli/test_setup_agent_settings.py -q` and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS 15.x

Documentation & Housekeeping

  • I've updated relevant documentation (README, `docs/`, docstrings) — or N/A
  • I've updated `cli-config.yaml.example` if I added/changed config keys — or N/A
  • I've updated `CONTRIBUTING.md` or `AGENTS.md` if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Screenshots / Logs

Before (issue repro): ``` $ hermes config show | grep -i 'max turns' Max turns: 200 $ # Telegram session shows: iteration 9/300 ← stale env value from prior wizard run ```

After this fix, repeated wizard runs no longer leave HERMES_MAX_ITERATIONS lines in .env, and the config-only edit path stays consistent with what every reader sees.

Changed files

  • hermes_cli/setup.py (modified, +4/-5)
  • tests/hermes_cli/test_setup_agent_settings.py (modified, +73/-12)
RAW_BUFFERClick to expand / collapse

Summary

`hermes_cli/setup.py` writes the "Max iterations" wizard answer to two places at once:

```python save_env_value("HERMES_MAX_ITERATIONS", str(max_iter)) # writes ~/.hermes/.env config.setdefault("agent", {})["max_turns"] = max_iter # writes config.yaml ```

Combined with the priority chain in `cli.py:2042-2051` (`config > env`), this creates a silent failure mode: any later edit to only one of the two stores leaves the other as a stale ghost. CLI `hermes config show` reports the config value (`200`), while sessions that load through paths preferring env may show the env value (`300`).

Repro symptom

After editing `agent.max_turns: 200` in config.yaml and restarting gateway:

  • `hermes config show` → `Max turns: 200`
  • Telegram session progress message → `iteration 9/300`

The 300 comes from a stale `HERMES_MAX_ITERATIONS=300` line in `.env` left by an earlier wizard run. Removing the env line restores consistency.

Why it bites users

  • `hermes setup` writes both stores once. Users expect config.yaml to be the source of truth (it's the only one shown in `hermes config show`).
  • A later config-only edit (manual, AI-assisted, or via `hermes config set`) leaves the env value as a ghost the user can't see in normal config inspection.
  • The error surfaces in long-running sessions resumed from suspended state, where the loaded `max_turns` may differ from the live config.

Suggestion

Pick a single source of truth. Either:

  1. Drop the env-var path — only write/read `config.yaml`, keeping `HERMES_MAX_ITERATIONS` for legacy install detection only (warn-and-migrate on startup if found).
  2. Or keep dual-write, but on `hermes config show` / `hermes config check` actively diff env vs config.yaml and warn on drift.

Option 1 is cleaner. Option 2 is backwards-compat-friendly.

A similar drift pattern likely exists for other wizard-managed values that also dual-write — worth a quick audit of all `save_env_value(...)` calls inside `setup.py`.

Reference

Closed issue #634 ("max_turns config has inconsistent defaults across modules") covered an adjacent symptom; this is the residual dual-store drift after that fix.

Environment

  • macOS 25.4.0
  • hermes-agent commit `a1921c43`

extent analysis

TL;DR

To resolve the silent failure mode caused by dual-writing "Max iterations" to both ~/.hermes/.env and config.yaml, pick a single source of truth, either by dropping the env-var path or keeping dual-write with active diff and warning on drift.

Guidance

  • Identify all instances of save_env_value calls in setup.py to check for similar dual-write patterns that could lead to stale values.
  • Consider dropping the env-var path for "Max iterations" and only use config.yaml as the source of truth to avoid inconsistencies.
  • If dual-write is kept, implement a diff check between env and config.yaml values on hermes config show or hermes config check to warn users of potential drift.
  • Review the impact of this change on legacy installations and plan for a smooth migration if necessary.

Example

No code snippet is provided as the issue description already includes relevant code excerpts.

Notes

The suggested fix may require additional changes to handle legacy installations and ensure a smooth transition to the new single source of truth.

Recommendation

Apply workaround by dropping the env-var path for "Max iterations" and only using config.yaml as the source of truth, as it is a cleaner solution that avoids potential inconsistencies.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix [Bug]: setup wizard double-writes max_turns to both .env (HERMES_MAX_ITERATIONS) and config.yaml (agent.max_turns), causing silent state drift [2 pull requests, 1 participants]