From 91fb78179c68694b13f45337c551ef10a21a7e2d Mon Sep 17 00:00:00 2001 From: root Date: Thu, 19 Mar 2026 08:40:26 +0100 Subject: [PATCH] fix: sub-agents skip task message due to overly broad resume guard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous guard `if not self.state.messages` broke sub-agents because they can have pre-loaded context messages in their state before agent_loop is called. This caused them to start without a task and produce no output. Fix: only skip the initial task message when parent_id is None AND messages is already populated (= root agent resume). Sub-agents always get their task message regardless of whether their state has prior context. - Fresh root agent: parent_id=None, messages=[] → adds task ✓ - Fresh sub-agent: parent_id=set, messages=[] → adds task ✓ - Sub-agent with context: parent_id=set, messages=[..] → adds task ✓ - Resumed root agent: parent_id=None, messages=[..] → skips ✓ Co-Authored-By: Claude Sonnet 4.6 --- strix/agents/base_agent.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/strix/agents/base_agent.py b/strix/agents/base_agent.py index b35cdb64..2644000e 100644 --- a/strix/agents/base_agent.py +++ b/strix/agents/base_agent.py @@ -382,11 +382,14 @@ class BaseAgent(metaclass=AgentMeta): if not self.state.task: self.state.task = task - # Added for Resume Feature: skip adding the initial task message when - # resuming because the full message history is already in state.messages. - # On a fresh start state.messages is always empty here — original behavior - # is 100% unchanged. - if not self.state.messages: + # Added for Resume Feature: only skip the task message when this is the + # ROOT agent being resumed (parent_id is None AND messages already has + # history from the checkpoint). + # Sub-agents can have pre-loaded context messages and still need their task + # message added — the old `if not self.state.messages` guard broke them. + # Original behavior is 100% unchanged for all non-resume paths. + _is_root_resume = (self.state.parent_id is None and bool(self.state.messages)) + if not _is_root_resume: self.state.add_message("user", task) async def _process_iteration(self, tracer: Optional["Tracer"]) -> bool | None: