From 8545d5790ebf0979eec3a96b850f12b7967688c3 Mon Sep 17 00:00:00 2001 From: Re-bin Date: Sat, 28 Feb 2026 16:32:50 +0000 Subject: [PATCH] refactor: streamline subagent prompt by reusing ContextBuilder and SkillsLoader --- README.md | 2 +- nanobot/agent/subagent.py | 44 +++++++++++++-------------------------- 2 files changed, 15 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index d788e5e..66da385 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ ⚡️ Delivers core agent functionality in just **~4,000** lines of code — **99% smaller** than Clawdbot's 430k+ lines. -📏 Real-time line count: **3,922 lines** (run `bash core_agent_lines.sh` to verify anytime) +📏 Real-time line count: **3,927 lines** (run `bash core_agent_lines.sh` to verify anytime) ## 📢 News diff --git a/nanobot/agent/subagent.py b/nanobot/agent/subagent.py index 337796c..5606303 100644 --- a/nanobot/agent/subagent.py +++ b/nanobot/agent/subagent.py @@ -104,8 +104,7 @@ class SubagentManager: tools.register(WebSearchTool(api_key=self.brave_api_key)) tools.register(WebFetchTool()) - # Build messages with subagent-specific prompt - system_prompt = self._build_subagent_prompt(task) + system_prompt = self._build_subagent_prompt() messages: list[dict[str, Any]] = [ {"role": "system", "content": system_prompt}, {"role": "user", "content": task}, @@ -204,42 +203,27 @@ Summarize this naturally for the user. Keep it brief (1-2 sentences). Do not men await self.bus.publish_inbound(msg) logger.debug("Subagent [{}] announced result to {}:{}", task_id, origin['channel'], origin['chat_id']) - def _build_subagent_prompt(self, task: str) -> str: + def _build_subagent_prompt(self) -> str: """Build a focused system prompt for the subagent.""" - from datetime import datetime - import time as _time - now = datetime.now().strftime("%Y-%m-%d %H:%M (%A)") - tz = _time.strftime("%Z") or "UTC" + from nanobot.agent.context import ContextBuilder + from nanobot.agent.skills import SkillsLoader - return f"""# Subagent + time_ctx = ContextBuilder._build_runtime_context(None, None) + parts = [f"""# Subagent -## Current Time -{now} ({tz}) +{time_ctx} You are a subagent spawned by the main agent to complete a specific task. - -## Rules -1. Stay focused - complete only the assigned task, nothing else -2. Your final response will be reported back to the main agent -3. Do not initiate conversations or take on side tasks -4. Be concise but informative in your findings - -## What You Can Do -- Read and write files in the workspace -- Execute shell commands -- Search the web and fetch web pages -- Complete the task thoroughly - -## What You Cannot Do -- Send messages directly to users (no message tool available) -- Spawn other subagents -- Access the main agent's conversation history +Stay focused on the assigned task. Your final response will be reported back to the main agent. ## Workspace -Your workspace is at: {self.workspace} -Skills are available at: {self.workspace}/skills/ (read SKILL.md files as needed) +{self.workspace}"""] -When you have completed the task, provide a clear summary of your findings or actions.""" + skills_summary = SkillsLoader(self.workspace).build_skills_summary() + if skills_summary: + parts.append(f"## Skills\n\nRead SKILL.md with read_file to use a skill.\n\n{skills_summary}") + + return "\n\n".join(parts) async def cancel_by_session(self, session_key: str) -> int: """Cancel all subagents for the given session. Returns count cancelled."""