From 9d6d76d9c91640b15349dda02427dbce3df06d9b Mon Sep 17 00:00:00 2001 From: "ilblackdragon@gmail.com" Date: Sun, 22 Mar 2026 00:35:56 -0700 Subject: [PATCH] fix(engine): add user message and system prompt to thread before execution The ExecutionLoop was sending empty messages to the LLM because the thread was spawned with the user's input as the goal but no messages. Fixes: - ThreadManager.spawn_thread() now adds the goal as an initial user message before starting the execution loop - ExecutionLoop.run() injects a default system prompt if none exists Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/ironclaw_engine/src/executor/loop_engine.rs | 11 +++++++++++ crates/ironclaw_engine/src/runtime/manager.rs | 3 +++ 2 files changed, 14 insertions(+) diff --git a/crates/ironclaw_engine/src/executor/loop_engine.rs b/crates/ironclaw_engine/src/executor/loop_engine.rs index bdb420b4..d1942068 100644 --- a/crates/ironclaw_engine/src/executor/loop_engine.rs +++ b/crates/ironclaw_engine/src/executor/loop_engine.rs @@ -61,6 +61,17 @@ impl ExecutionLoop { // Transition to Running self.thread.transition_to(ThreadState::Running, None)?; + // Inject system prompt if none exists + if !self.thread.messages.iter().any(|m| m.role == crate::types::message::MessageRole::System) { + self.thread.messages.insert( + 0, + ThreadMessage::system( + "You are a helpful assistant. Use the available tools to accomplish the user's request. \ + Respond concisely.", + ), + ); + } + let max_iterations = self.thread.config.max_iterations; let max_nudges = self.thread.config.max_tool_intent_nudges; let nudge_enabled = self.thread.config.enable_tool_intent_nudge; diff --git a/crates/ironclaw_engine/src/runtime/manager.rs b/crates/ironclaw_engine/src/runtime/manager.rs index b84d218a..f94846a1 100644 --- a/crates/ironclaw_engine/src/runtime/manager.rs +++ b/crates/ironclaw_engine/src/runtime/manager.rs @@ -95,6 +95,9 @@ impl ThreadManager { thread.capability_leases.push(lease.id); } + // Add the goal as the initial user message so the LLM has context + thread.add_message(crate::types::message::ThreadMessage::user(&thread.goal)); + // Persist self.store.save_thread(&thread).await?;