Bug Description
When a sub agent wave is ongoing, slash commands are broken! Each slash command is handled differently during the sub agent wave. /new does not work at all, /redraw worked, /clear did clear BUT agent still had full context.
Steps to Reproduce
- tell main agent to spawn a sub agent wave 4 sub agents.
- type: /new
- /new should never go thru even when wave is complete.
- same with /clear on the front end, the session is cleared but context is actually retained.
Expected Behavior
/new should immediately create a new session and NOT allow any context from the old session including any return from the sub agents.
/clear should clear the context under the same session immediately.
Actual Behavior
during the sub agent wave, I tried /new, /redraw (worked) and /clear (acted like it worked but did not).
Affected Component
Other
Messaging Platform (if gateway-related)
N/A (CLI only)
Debug Report
Zadie_bug_report_subagent_slash_interrupt.md
---
# Bug Report: Slash Command Failure During Active Subagent Delegation
Date: 2026-07-12
Reporter: Hermies Zadie (CONTAK Mr Trench Worker)
Harness Version: 0.18.0 (v2026.7.1-dirty)
Severity: High (Blocks user interrupt/refresh during long-running tasks)
Status: Root Cause Identified, Fix Proposed
---
## 1. Executive Summary
Slash commands (specifically destructive ones like /new, /clear, and potentially /quit) fail to take effect when a user attempts them while a batch of subagents (via delegate_task) is actively running.
The parent agent ignores the command or queues it incorrectly, leaving the user stuck waiting for subagents to finish naturally. This breaks the core user expectation that destructive commands should immediately abort all work and start fresh.
---
## 2. The Symptom
User Experience:
1. User dispatches a multi-agent research task (e.g., "Find all X and write 3 chapters").
2. Subagents spawn and start working (takes 2-5 minutes).
3. User realizes they want to abort/correct the task and types /new "Better prompt".
4. Result: The command seems to do nothing. The UI shows "Agent busy" or the command output is swallowed. The subagents continue running until completion.
5. The user is forced to wait for the full delegation to finish or kill the terminal process (KILL9).
Expected Behavior:
- /new should immediately interrupt all running subagents, clear the context, and start a fresh session.
- /clear should abort all background work and reset the conversation history.
---
## 3. Root Cause Analysis
### 3.1 The Architecture
- Subagent Spawning: When delegate_task is called, the parent agent registers child agents in self.\_active_children (list) inside tools/delegate_tool.py.
- Interrupt Mechanism: The parent has \_interrupt_requested (bool) and \_active_children (list).
- Interrupt Propagation: The AIAgent.interrupt() method iterates over \_active_children and calls child.interrupt() on each.
### 3.2 The Code Defect
File: run_agent.pyFunction: clear_interrupt() (Lines 2686-2718)
The clear_interrupt() method ONLY clears the parent's flag. It does NOT propagate the "clear" signal to children.
def clear_interrupt(self) -> None:
"""Clear any pending interrupt request and the per-thread tool interrupt signal."""
self._interrupt_requested = False
self._interrupt_message = None
self._interrupt_thread_signal_pending = False
# ... clears tool worker threads ...
# ❌ MISSING: Propagation to children
# There is NO code here that says:
# for child in self._active_children:
# child.clear_interrupt()
File: cli.pyFunction: process_command() (Lines 8370-8450)
When a destructive slash command like /new or /clear is executed:
1. It calls self.new_session() or self.clear_terminal().
2. Inside new_session(), the code calls self.agent.close() and self.agent.clear_interrupt().
3. The Critical Failure: clear_interrupt() returns immediately after clearing the parent flag.
4. The children are still running, still holding their own \_interrupt_requested = False (because they were never signaled to stop).
Contrast with interrupt():
The interrupt() method (Lines 2642-2684) DOES propagate to children correctly:
def interrupt(self, message=None):
self._interrupt_requested = True
# ... fan out to children ...
with self._active_children_lock:
children_copy = list(self._active_children)
for child in children_copy:
try:
child.interrupt(message) # ✅ Correct propagation
### 3.3 Why process_command Bypasses the Fix
The CLI's process_command method for /new and /clear calls clear_interrupt() directly (via new_session()) instead of going through a unified "abort everything" entry point.
The flow is:
1. User types /new
2. cli.py → process_command("/new") → new_session()
3. new_session() → agent.close() → agent.clear_interrupt()
4. clear_interrupt() clears parent only. Children keep running.
5. new_session() spawns a new agent with a new ID.
6. The children are now orphaned: they are still attached to the old parent session ID but the parent session is dead.
---
## 4. Reproduction Steps
1. Start Hermes CLI.
2. Dispatch a long-running subagent task (e.g., "Write a 10-page report on X" or delegate_task with a sleep loop).
3. While subagents are running (check /kanban list or the TUI overlay), type:
/new "Cancel everything and start fresh"
4. Observe:
- The command prints a "starting new session" message but the prompt never returns.
- Subagents continue to log work in the background.
- The Kafka-stream of tool output from the subagents does not stop.
- The new session does not actually start until the old subagents finish naturally.
---
## 5. Proposed Fix
### Option A: Patch clear_interrupt() (Recommended)
Modify run_agent.py to propagate the "clear" signal to all active children before clearing the parent flag.
File: run_agent.pyLocation: AIAgent.clear_interrupt() (after line 2688)
def clear_interrupt(self) -> None:
"""Clear any pending interrupt request and the per-thread tool interrupt signal."""
# ✅ FIX: Propagate clear to active children BEFORE clearing parent flag
with self._active_children_lock:
children_copy = list(self._active_children)
for child in children_copy:
try:
child.clear_interrupt()
except Exception as e:
logger.debug("Failed to clear interrupt on child agent: %s", e)
self._interrupt_requested = False
self._interrupt_message = None
self._interrupt_thread_signal_pending = False
# ... rest of existing clear_interrupt() logic ...
Why this works:
- Ensures that any code path that calls clear_interrupt() (slash commands, manual close) automatically wakes up and tells children to "stop."
- Maintains symmetry: interrupt() propagates down; clear_interrupt() propagates down.
- No changes needed in cli.py.
### Option B: Add a Unified abort() Method
Create AIAgent.abort() that calls interrupt() then close(), and route all destructive slash commands through this new method.
Pros: More explicit intent.
Cons: Requires changes in cli.py and run_agent.py. Slightly diffusing.
Option A is preferred for minimal churn and maximum backward compatibility.
---
## 6. Testing Strategy
After applying the fix:
1. Unit Test: Add a test in tests/cli/test_slash_command_interrupt.py or tests/cli/test_cli_interrupt_subagent.py.
- Mock a parent with 2 active children.
- Call parent.clear_interrupt().
- Assert child1.\_interrupt_requested became False (or child1.interrupt_was_called flag set).
- Assert child2.\_interrupt_requested became False.
2. Integration Test:
- Start a subagent task that sleeps for 60 seconds.
- Type /new at T+10s.
- Verify the subagent logs "Interrupt requested" and exits within 5 seconds.
- Verify the new session starts immediately without waiting for the 60s timer.
3. Edge Case:
- Verify that clear_interrupt() on a parent with no children does not raise errors.
---
## 7. Impact Assessment
- Breaking Changes: None. This fixes a bug where commands failed, restoring expected behavior.
- Performance: Negligible. The loop over \_active_children is O(n) where n is usually < 5.
- Security: No impact.
- Backport Target: v0.18.0 (Current release).
---
## 8. Related Issues / References
- tests/cli/test_cli_interrupt_subagent.py: Existing test for user-typed interrupts (does not cover slash commands).
- run_agent.py: Lines 2642-2718 (interrupt() vs clear_interrupt()).
- cli.py: Lines 8240-8450 (process_command dispatch logic).
- tools/delegate_tool.py: Lines 45-54 (DELEGATE_BLOCKED_TOOLS and spawn logic).
---
## 9. Next Steps
1. Apply Option A fix to run_agent.py.
2. Run existing interrupt tests to ensure no regressions.
3. Add new integration test for slash command + subagent scenario.
4. Submit PR to main with label bugfix and high-priority.
5. Trigger hotfix release if necessary (if v0.18.0 is already shipped to users).
---
Report generated by Hermies Zadie, HANDS Worker.Harness Version: 0.18.0 | Date: 2026-07-12
Operating System
Linux Truenas Scale (goldeneye)
Python Version
No response
Hermes Version
v0.18.0
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
No response
Proposed Fix (optional)
slash commands should work during sub agent waves.
Are you willing to submit a PR for this?
Bug Description
When a sub agent wave is ongoing, slash commands are broken! Each slash command is handled differently during the sub agent wave. /new does not work at all, /redraw worked, /clear did clear BUT agent still had full context.
Steps to Reproduce
Expected Behavior
/new should immediately create a new session and NOT allow any context from the old session including any return from the sub agents.
/clear should clear the context under the same session immediately.
Actual Behavior
during the sub agent wave, I tried /new, /redraw (worked) and /clear (acted like it worked but did not).
Affected Component
Other
Messaging Platform (if gateway-related)
N/A (CLI only)
Debug Report
Operating System
Linux Truenas Scale (goldeneye)
Python Version
No response
Hermes Version
v0.18.0
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
No response
Proposed Fix (optional)
slash commands should work during sub agent waves.
Are you willing to submit a PR for this?