forked from molecule-ai/molecule-core
Merge pull request #1049 from Molecule-AI/feat/platform-native-hma-instructions
feat(runtime): inject HMA memory instructions at platform level (#1047)
This commit is contained in:
commit
d3b310e895
@ -50,6 +50,7 @@ from executor_helpers import (
|
||||
commit_memory,
|
||||
extract_message_text,
|
||||
get_a2a_instructions,
|
||||
get_hma_instructions,
|
||||
get_mcp_server_path,
|
||||
get_system_prompt,
|
||||
read_delegation_results,
|
||||
@ -211,12 +212,12 @@ class ClaudeSDKExecutor(AgentExecutor):
|
||||
return CONFIG_MOUNT
|
||||
|
||||
def _build_system_prompt(self) -> str | None:
|
||||
"""Compose system prompt from file + A2A delegation instructions."""
|
||||
"""Compose system prompt from file + A2A + HMA memory instructions."""
|
||||
base = get_system_prompt(self.config_path, fallback=self.system_prompt)
|
||||
a2a = get_a2a_instructions(mcp=True)
|
||||
if base and a2a:
|
||||
return f"{base}\n\n{a2a}"
|
||||
return base or a2a
|
||||
hma = get_hma_instructions()
|
||||
parts = [p for p in (base, a2a, hma) if p]
|
||||
return "\n\n".join(parts) if parts else None
|
||||
|
||||
def _prepare_prompt(self, user_input: str) -> str:
|
||||
"""Prepend delegation results that arrived while idle."""
|
||||
|
||||
@ -290,6 +290,31 @@ def get_a2a_instructions(mcp: bool = True) -> str:
|
||||
return _A2A_INSTRUCTIONS_MCP if mcp else _A2A_INSTRUCTIONS_CLI
|
||||
|
||||
|
||||
_HMA_INSTRUCTIONS = """## Hierarchical Memory (HMA)
|
||||
You have persistent memory tools that survive across sessions and restarts:
|
||||
|
||||
- **commit_memory(content, scope)**: Save important information.
|
||||
- LOCAL: private to you only (default)
|
||||
- TEAM: shared with your parent workspace and siblings (same team)
|
||||
- GLOBAL: shared with the entire org (only root workspaces can write)
|
||||
|
||||
- **recall_memory(query)**: Search your accessible memories. Returns LOCAL + TEAM + GLOBAL matches.
|
||||
|
||||
**When to use memory:**
|
||||
- After making a decision or learning something non-obvious → commit_memory("decision X because Y", scope="TEAM")
|
||||
- Before starting work → recall_memory("what did the team decide about X")
|
||||
- When you discover org-wide knowledge (repo locations, API patterns, conventions) → commit_memory(fact, scope="GLOBAL") if you are a root workspace, or scope="TEAM" to share with your team
|
||||
- After completing a task → commit_memory("completed task X, PR #N opened", scope="TEAM") so your lead and teammates know
|
||||
|
||||
**Memory is automatically recalled** at the start of each new session. Use it proactively during work to share context.
|
||||
"""
|
||||
|
||||
|
||||
def get_hma_instructions() -> str:
|
||||
"""Return HMA memory instructions for system-prompt injection."""
|
||||
return _HMA_INSTRUCTIONS
|
||||
|
||||
|
||||
# ========================================================================
|
||||
# Misc text helpers
|
||||
# ========================================================================
|
||||
|
||||
@ -479,7 +479,8 @@ def test_build_system_prompt_combines_base_and_a2a_via_fixture():
|
||||
"""Direct test bypassing the execute() path."""
|
||||
e = _make_executor()
|
||||
with patch("claude_sdk_executor.get_system_prompt", return_value="BASE"), \
|
||||
patch("claude_sdk_executor.get_a2a_instructions", return_value="A2A"):
|
||||
patch("claude_sdk_executor.get_a2a_instructions", return_value="A2A"), \
|
||||
patch("claude_sdk_executor.get_hma_instructions", return_value=""):
|
||||
out = e._build_system_prompt()
|
||||
assert out == "BASE\n\nA2A"
|
||||
|
||||
@ -487,17 +488,31 @@ def test_build_system_prompt_combines_base_and_a2a_via_fixture():
|
||||
def test_build_system_prompt_base_only():
|
||||
e = _make_executor()
|
||||
with patch("claude_sdk_executor.get_system_prompt", return_value="BASE"), \
|
||||
patch("claude_sdk_executor.get_a2a_instructions", return_value=""):
|
||||
patch("claude_sdk_executor.get_a2a_instructions", return_value=""), \
|
||||
patch("claude_sdk_executor.get_hma_instructions", return_value=""):
|
||||
assert e._build_system_prompt() == "BASE"
|
||||
|
||||
|
||||
def test_build_system_prompt_a2a_only():
|
||||
e = _make_executor()
|
||||
with patch("claude_sdk_executor.get_system_prompt", return_value=None), \
|
||||
patch("claude_sdk_executor.get_a2a_instructions", return_value="A2A"):
|
||||
patch("claude_sdk_executor.get_a2a_instructions", return_value="A2A"), \
|
||||
patch("claude_sdk_executor.get_hma_instructions", return_value=""):
|
||||
assert e._build_system_prompt() == "A2A"
|
||||
|
||||
|
||||
def test_build_system_prompt_includes_hma():
|
||||
"""HMA instructions are appended when present."""
|
||||
e = _make_executor()
|
||||
with patch("claude_sdk_executor.get_system_prompt", return_value="BASE"), \
|
||||
patch("claude_sdk_executor.get_a2a_instructions", return_value="A2A"), \
|
||||
patch("claude_sdk_executor.get_hma_instructions", return_value="## Hierarchical Memory"):
|
||||
out = e._build_system_prompt()
|
||||
assert "BASE" in out
|
||||
assert "A2A" in out
|
||||
assert "## Hierarchical Memory" in out
|
||||
|
||||
|
||||
def test_prepare_prompt_no_delegation_returns_unchanged():
|
||||
e = _make_executor()
|
||||
with patch("claude_sdk_executor.read_delegation_results", return_value=""):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user