From a5f21c7e6fec5987cbb8ce381015f68b3c0d4cba Mon Sep 17 00:00:00 2001 From: Jorge Zambrano Date: Thu, 26 Mar 2026 18:56:37 -0400 Subject: [PATCH] fix(plugin): prevent sub-agent infinite loop on session lifecycle calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sub-agents (Explore, etc.) inherit the engram memory protocol and interpret their task completion as a session close, entering an infinite loop of mem_session_summary → mem_context → mem_session_summary calls. With bypassPermissions enabled, sessions hang for up to 1 hour. Add "SUB-AGENT SCOPE" sections to the injected protocol text in session-start.sh, post-compaction.sh, and memory/SKILL.md that explicitly tell sub-agents to skip session lifecycle tools (mem_session_start, mem_session_end, mem_session_summary). Scope SESSION CLOSE and AFTER COMPACTION headers as TOP-LEVEL AGENT ONLY so the mandatory language no longer applies to delegated tasks. Closes #128 --- plugin/claude-code/scripts/post-compaction.sh | 10 ++++++++-- plugin/claude-code/scripts/session-start.sh | 8 +++++++- plugin/claude-code/skills/memory/SKILL.md | 17 ++++++++++++++--- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/plugin/claude-code/scripts/post-compaction.sh b/plugin/claude-code/scripts/post-compaction.sh index b556ccc..0eacf2a 100755 --- a/plugin/claude-code/scripts/post-compaction.sh +++ b/plugin/claude-code/scripts/post-compaction.sh @@ -60,12 +60,18 @@ Call `mem_save` IMMEDIATELY after ANY of these: - Starting work on something that might have been done before - User mentions a topic you have no context on -### SESSION CLOSE — before saying "done"/"listo": +### SUB-AGENT SCOPE +If you are a sub-agent or delegated task (launched by an orchestrator/parent agent): +- DO NOT call `mem_session_start`, `mem_session_end`, or `mem_session_summary` +- You MAY call `mem_save` once for important discoveries, and `mem_search`/`mem_context` as needed +- Return your result to the parent agent when done — that is your only "close" action + +### SESSION CLOSE — TOP-LEVEL AGENT ONLY, before saying "done"/"listo": Call `mem_session_summary` with: Goal, Discoveries, Accomplished, Next Steps, Relevant Files. --- -CRITICAL INSTRUCTION POST-COMPACTION — follow these steps IN ORDER: +CRITICAL INSTRUCTION POST-COMPACTION (TOP-LEVEL AGENT ONLY) — follow these steps IN ORDER: PROTOCOL printf "\n1. FIRST: Call mem_session_summary with the content of the compacted summary above. Use project: '%s'.\n" "$PROJECT" diff --git a/plugin/claude-code/scripts/session-start.sh b/plugin/claude-code/scripts/session-start.sh index 8365e10..adc562b 100755 --- a/plugin/claude-code/scripts/session-start.sh +++ b/plugin/claude-code/scripts/session-start.sh @@ -88,7 +88,13 @@ Call `mem_save` IMMEDIATELY after ANY of these: - User mentions a topic you have no context on - User's FIRST message references the project, a feature, or a problem — call `mem_search` with keywords from their message to check for prior work before responding -### SESSION CLOSE — before saying "done"/"listo": +### SUB-AGENT SCOPE +If you are a sub-agent or delegated task (launched by an orchestrator/parent agent): +- DO NOT call `mem_session_start`, `mem_session_end`, or `mem_session_summary` +- You MAY call `mem_save` once for important discoveries, and `mem_search`/`mem_context` as needed +- Return your result to the parent agent when done — that is your only "close" action + +### SESSION CLOSE — TOP-LEVEL AGENT ONLY, before saying "done"/"listo": Call `mem_session_summary` with: Goal, Discoveries, Accomplished, Next Steps, Relevant Files. PROTOCOL diff --git a/plugin/claude-code/skills/memory/SKILL.md b/plugin/claude-code/skills/memory/SKILL.md index cde2b97..00f0d96 100644 --- a/plugin/claude-code/skills/memory/SKILL.md +++ b/plugin/claude-code/skills/memory/SKILL.md @@ -88,9 +88,20 @@ Also search memory PROACTIVELY when: - The user mentions a topic you have no context on — check if past sessions covered it - The user's FIRST message references the project, a feature, or a problem — call `mem_search` with keywords from their message to check for prior work before responding -## SESSION CLOSE PROTOCOL (mandatory) +## SUB-AGENT / DELEGATED TASK SCOPE -Before ending a session or saying "done" / "listo" / "that's it", you MUST: +If you are running as a sub-agent, delegated task, or background worker (i.e., you were launched by an orchestrator or parent agent to perform a specific task): +- **DO NOT** call `mem_session_start`, `mem_session_end`, or `mem_session_summary` +- **DO NOT** follow the SESSION CLOSE PROTOCOL below +- You MAY call `mem_save` for genuinely important discoveries (once, not repeatedly) +- You MAY call `mem_search` or `mem_context` if needed for your task +- When your task is complete, return your result to the parent agent. That is your only "close" action. + +Session lifecycle (start, summary, end) is the responsibility of the TOP-LEVEL agent that directly interacts with the human user. + +## SESSION CLOSE PROTOCOL (mandatory — TOP-LEVEL AGENT ONLY) + +Before ending a TOP-LEVEL session (direct human conversation) or saying "done" / "listo" / "that's it", you MUST: 1. Call `mem_session_summary` with this structure: ## Goal @@ -113,7 +124,7 @@ Before ending a session or saying "done" / "listo" / "that's it", you MUST: This is NOT optional. If you skip this, the next session starts blind. -## AFTER COMPACTION +## AFTER COMPACTION (TOP-LEVEL AGENT ONLY) If you see a message about compaction or context reset: 1. IMMEDIATELY call `mem_session_summary` with the compacted summary content — this persists what was done before compaction