Skip to content

fix(cli): forward system prompt overlay in oneshot (-z) mode (supersedes #34863) - #69957

Open
hey-ynot wants to merge 1 commit into
NousResearch:mainfrom
hey-ynot:fix/oneshot-system-prompt-forwarding-v2
Open

fix(cli): forward system prompt overlay in oneshot (-z) mode (supersedes #34863)#69957
hey-ynot wants to merge 1 commit into
NousResearch:mainfrom
hey-ynot:fix/oneshot-system-prompt-forwarding-v2

Conversation

@hey-ynot

Copy link
Copy Markdown

Summary

hermes -z builds its AIAgent directly in hermes_cli/oneshot.py:_run_agent() (L313) and never forwards the system-prompt overlay, so HERMES_EPHEMERAL_SYSTEM_PROMPT and the configured agent.system_prompt are silently ignored in oneshot mode.

Verified on current main (8fc278207):

  • interactive CLI resolves the overlay at cli.py:3992 and forwards it at hermes_cli/cli_agent_setup_mixin.py:369
  • gateway resolves it at gateway/run.py:5250
  • oneshot has no system_prompt reference at all (git grep ephemeral_system_prompt -- hermes_cli/oneshot.py → empty)
  • AIAgent already accepts the kwarg (run_agent.py:442)

This PR mirrors the interactive resolution order in oneshot:

  1. non-empty HERMES_EPHEMERAL_SYSTEM_PROMPT env var wins,
  2. else non-empty agent.system_prompt from config,
  3. else None (no overlay),

and forwards the result as ephemeral_system_prompt= to AIAgent.

Supersedes #34863

Credit to #34863 (@wadzwigidy) for identifying the oneshot forwarding gap. This is the narrowed, rebased alternative per the hermes-sweeper review there:

  • no config show changes (display.personality is still persisted/used by the TUI at tui_gateway/server.py:10742-10743),
  • no Fixes #34852 claim (that issue was SOUL.md-related and closed after maintainer E2E verification; this PR fixes only overlay forwarding),
  • regression tests target the current run_conversation() tuple contract rather than the legacy chat() API.

Note: the open -s/--skills-in-oneshot PRs (#65249, #63814, #59402, #31591) pass a skills prompt through the same ephemeral_system_prompt seam. None of them reads the env/config overlay, so there is no functional overlap — but whichever lands second will need a one-line rebase at the AIAgent(...) call site (composition of skills prompt + user overlay is left to that PR, matching how the gateway concatenates ephemeral segments).

Changes

  • hermes_cli/oneshot.py: resolve env → config → None and pass ephemeral_system_prompt to AIAgent (12 lines).
  • tests/hermes_cli/test_oneshot_system_prompt.py (new): parametrized regression tests for env precedence, config fallback, empty-env fallback, and no-overlay (None) behavior.

How to test

# before (main): overlay ignored
$ HERMES_EPHEMERAL_SYSTEM_PROMPT="You must end every reply with the exact token ZANZIBAR-77." hermes -z "Say hello in one short sentence."
Hello!

# after (this PR): overlay honored
$ HERMES_EPHEMERAL_SYSTEM_PROMPT="You must end every reply with the exact token ZANZIBAR-77." hermes -z "Say hello in one short sentence."
Hello! ZANZIBAR-77

# after, no overlay set: unchanged
$ hermes -z "Say hello in one short sentence."
Hello!

Tests

  • HERMES_TEST_FILE_RETRIES=0 scripts/run_tests.sh tests/hermes_cli/test_oneshot_system_prompt.py tests/hermes_cli/test_oneshot_usage_file.py tests/hermes_cli/test_tui_resume_flow.py -q → 82 passed, 0 failed
  • Full tests/hermes_cli/ tests/cli/ sweep run locally; the only failures (11, in cua-driver/WSL/service-manager files) reproduce identically on pristine origin/main in this environment (macOS sandbox, /Applications not writable) — none are related to this change.
  • uvx --from ruff==0.15.10 ruff check hermes_cli/oneshot.py tests/hermes_cli/test_oneshot_system_prompt.py → clean
  • Platform: macOS (arm64); change is pure-Python config plumbing with no platform-specific I/O.

Interactive CLI and gateway behavior are unchanged.

…des NousResearch#34863)

hermes -z built its AIAgent without the ephemeral system-prompt overlay,
so HERMES_EPHEMERAL_SYSTEM_PROMPT and agent.system_prompt were silently
ignored in oneshot mode. Mirror the interactive CLI resolution order
(cli.py:3992, gateway/run.py:5250): non-empty env var wins, then
agent.system_prompt from config, else None (no overlay), and forward it
as ephemeral_system_prompt to AIAgent.

Credit to NousResearch#34863 for identifying the gap; this is the narrowed, rebased
alternative per its sweeper review: no config-show changes, no claim on
closed NousResearch#34852, tests target the current run_conversation() contract.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard area/config Config system, migrations, profiles sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades needs-decision Awaiting maintainer decision before any implementation labels Jul 23, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to #34863. This narrowed alternative addresses the recorded config-show scope and stale test-contract concerns while retaining the same oneshot overlay-forwarding goal; maintainer selection is needed.

@hey-ynot hey-ynot added type/bug Something isn't working comp/cli CLI entry point, hermes_cli/, setup wizard area/config Config system, migrations, profiles P2 Medium — degraded but workaround exists needs-decision Awaiting maintainer decision before any implementation sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Jul 23, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the narrowly scoped fix. The current-head premise is confirmed: hermes_cli/oneshot.py:330 loads config, but its only AIAgent construction at hermes_cli/oneshot.py:410-435 does not pass an ephemeral system prompt. This differs from the interactive CLI, which resolves the same env-over-config order at cli.py:4470-4474 and forwards it at hermes_cli/cli_agent_setup_mixin.py:377.

The proposed forwarding reaches the real wire behavior: agent/agent_init.py:581 stores the value, and agent/chat_completion_helpers.py:2152-2156 appends it to the API system message while agent/system_prompt.py:477-480 keeps it out of the cached prompt. The added parametrized regression test in tests/hermes_cli/test_oneshot_system_prompt.py:58-83 covers the stated precedence and empty-value cases.

Automated hermes-sweeper review.

@teknium1 teknium1 added the sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users label Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard needs-decision Awaiting maintainer decision before any implementation P2 Medium — degraded but workaround exists sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants