Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions cron/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -1033,10 +1033,12 @@ def run_job(job: dict) -> tuple[bool, str, str, Optional[str]]:
enabled_toolsets=_resolve_cron_enabled_toolsets(job, _cfg),
disabled_toolsets=["cronjob", "messaging", "clarify"],
quiet_mode=True,
# When a workdir is configured, inject AGENTS.md / CLAUDE.md /
# .cursorrules from that directory; otherwise preserve the old
# behaviour (don't inject SOUL.md/AGENTS.md from the scheduler cwd).
# Cron jobs should always inherit the user's SOUL.md identity from
# HERMES_HOME. When a workdir is configured, also inject project
# context files (AGENTS.md / CLAUDE.md / .cursorrules) from there.
# Without a workdir, keep cwd context discovery disabled.
skip_context_files=not bool(_job_workdir),
load_soul_identity=True,
skip_memory=True, # Cron system prompts would corrupt user representations
platform="cron",
session_id=_cron_session_id,
Expand Down
11 changes: 9 additions & 2 deletions run_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,7 @@ def __init__(
thread_id: str = None,
gateway_session_key: str = None,
skip_context_files: bool = False,
load_soul_identity: bool = False,
skip_memory: bool = False,
session_db=None,
parent_session_id: str = None,
Expand Down Expand Up @@ -977,6 +978,9 @@ def __init__(
skip_context_files (bool): If True, skip auto-injection of SOUL.md, AGENTS.md, and .cursorrules
into the system prompt. Use this for batch processing and data generation to avoid
polluting trajectories with user-specific persona or project instructions.
load_soul_identity (bool): If True, still use ~/.hermes/SOUL.md as the primary
identity even when skip_context_files=True. Project context files from the cwd
remain skipped.
"""
_install_safe_stdio()

Expand Down Expand Up @@ -1005,6 +1009,7 @@ def __init__(
self._print_fn = None
self.background_review_callback = None # Optional sync callback for gateway delivery
self.skip_context_files = skip_context_files
self.load_soul_identity = load_soul_identity
self.pass_session_id = pass_session_id
self._credential_pool = credential_pool
self.log_prefix_chars = log_prefix_chars
Expand Down Expand Up @@ -4742,9 +4747,11 @@ def _build_system_prompt(self, system_message: str = None) -> str:
# 6. Current date & time (frozen at build time)
# 7. Platform-specific formatting hint

# Try SOUL.md as primary identity (unless context files are skipped)
# Try SOUL.md as primary identity unless the caller explicitly skipped it.
# Some execution modes (cron) still want HERMES_HOME persona while keeping
# cwd project instructions disabled.
_soul_loaded = False
if not self.skip_context_files:
if self.load_soul_identity or not self.skip_context_files:
_soul_content = load_soul_md()
if _soul_content:
prompt_parts = [_soul_content]
Expand Down
1 change: 1 addition & 0 deletions scripts/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"beliefanx@gmail.com": "BeliefanX",
"jefferson@heimdallstrategy.com": "Mind-Dragon",
"steve.westerhouse@origami-analytics.com": "westers",
"liuhao03@bilibili.com": "liuhao1024",
"130918800+devorun@users.noreply.github.com": "devorun",
"surat.s@itm.kmutnb.ac.th": "beesrsj2500",
"beesr@bee.localdomain": "beesrsj2500",
Expand Down
4 changes: 4 additions & 0 deletions tests/cron/test_cron_workdir.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ def _install_stubs(monkeypatch, observed: dict):
class FakeAgent:
def __init__(self, **kwargs):
observed["skip_context_files"] = kwargs.get("skip_context_files")
observed["load_soul_identity"] = kwargs.get("load_soul_identity")
observed["terminal_cwd_during_init"] = os.environ.get(
"TERMINAL_CWD", "_UNSET_"
)
Expand Down Expand Up @@ -335,6 +336,7 @@ def test_workdir_sets_and_restores_terminal_cwd(

# AIAgent was built with skip_context_files=False (feature ON).
assert observed["skip_context_files"] is False
assert observed["load_soul_identity"] is True
# TERMINAL_CWD was pointing at the job workdir while the agent ran.
assert observed["terminal_cwd_during_init"] == str(tmp_path.resolve())
assert observed["terminal_cwd_during_run"] == str(tmp_path.resolve())
Expand Down Expand Up @@ -373,6 +375,8 @@ def test_no_workdir_leaves_terminal_cwd_untouched(self, monkeypatch):

# Feature is OFF — skip_context_files stays True.
assert observed["skip_context_files"] is True
# Cron still forces SOUL.md identity even when cwd context files stay off.
assert observed["load_soul_identity"] is True
# TERMINAL_CWD saw the same value during init as it had before.
assert observed["terminal_cwd_during_init"] == before
# And after run_job completes, it's still the sentinel (nothing
Expand Down
20 changes: 20 additions & 0 deletions tests/run_agent/test_run_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,26 @@ def test_always_has_identity(self, agent):
prompt = agent._build_system_prompt()
assert DEFAULT_AGENT_IDENTITY in prompt

def test_can_use_soul_identity_even_when_context_files_are_skipped(self):
with (
patch("run_agent.get_tool_definitions", return_value=_make_tool_defs("terminal")),
patch("run_agent.check_toolset_requirements", return_value={}),
patch("run_agent.OpenAI"),
patch("run_agent.load_soul_md", return_value="SOUL IDENTITY"),
):
agent = AIAgent(
api_key="test-k...7890",
base_url="https://openrouter.ai/api/v1",
quiet_mode=True,
skip_context_files=True,
load_soul_identity=True,
skip_memory=True,
)
prompt = agent._build_system_prompt()

assert "SOUL IDENTITY" in prompt
assert DEFAULT_AGENT_IDENTITY not in prompt

def test_includes_system_message(self, agent):
prompt = agent._build_system_prompt(system_message="Custom instruction")
assert "Custom instruction" in prompt
Expand Down
Loading