From c3ab7985d25652f8e655d0d68185f85b12b1f02f Mon Sep 17 00:00:00 2001 From: iven Date: Mon, 6 Apr 2026 13:11:49 +0800 Subject: [PATCH] =?UTF-8?q?refactor(skills):=20progressive=20skill=20loadi?= =?UTF-8?q?ng=20=E2=80=94=20avoid=20duplicate=20injection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When SkillIndexMiddleware is active, build_system_prompt_with_skills no longer injects the full categorized skill list. Instead it only adds usage instructions, while the middleware handles the lightweight index. This reduces ~2000 tokens per request for the 75-skill system. --- crates/zclaw-kernel/src/kernel/messaging.rs | 67 +++++++++++++-------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/crates/zclaw-kernel/src/kernel/messaging.rs b/crates/zclaw-kernel/src/kernel/messaging.rs index 20e4a1a..2b52640 100644 --- a/crates/zclaw-kernel/src/kernel/messaging.rs +++ b/crates/zclaw-kernel/src/kernel/messaging.rs @@ -229,35 +229,54 @@ impl Kernel { .map(|p| p.clone()) .unwrap_or_else(|| "You are a helpful AI assistant.".to_string()); - // Inject skill metadata only (progressive loading pattern from DeerFlow). - // Full skill content is loaded on-demand via `load_skill_content` tool. + // Progressive skill loading (DeerFlow pattern): + // If the SkillIndexMiddleware is registered in the middleware chain, + // it will inject a lightweight index at priority 200. + // We still inject a basic instruction block here for when middleware is not active. + // + // When middleware IS active, avoid duplicate injection by only keeping + // the skill-use instructions (not the full list). + let skill_index_active = { + use zclaw_runtime::tool::SkillExecutor; + !self.skill_executor.list_skill_index().is_empty() + }; + if !skills.is_empty() { - prompt.push_str("\n\n## Available Skills\n\n"); - prompt.push_str("You have access to specialized skills. Analyze user intent and autonomously call `execute_skill` with the appropriate skill_id.\n\n"); + if skill_index_active { + // Middleware will inject the index — only add usage instructions + prompt.push_str("\n\n## Skills\n\n"); + prompt.push_str("You have access to specialized skills listed in the skill index above. "); + prompt.push_str("Analyze user intent and autonomously call `skill_load` to inspect a skill, "); + prompt.push_str("then `execute_skill` with the appropriate skill_id.\n\n"); + prompt.push_str("- **IMPORTANT**: Autonomously decide when to use skills based on user intent.\n"); + prompt.push_str("- Do not wait for explicit skill names — recognize the need and act.\n"); + prompt.push_str("- If unsure about a skill, call `skill_load` first to understand its parameters.\n"); + } else { + // No middleware — inject full skill list as fallback + prompt.push_str("\n\n## Available Skills\n\n"); + prompt.push_str("You have access to specialized skills. Analyze user intent and autonomously call `execute_skill` with the appropriate skill_id.\n\n"); - // Group skills by category based on their ID patterns - let categories = self.categorize_skills(&skills); - - for (category, category_skills) in categories { - prompt.push_str(&format!("### {}\n", category)); - for skill in category_skills { - prompt.push_str(&format!( - "- **{}**: {}", - skill.id.as_str(), - skill.description - )); + let categories = self.categorize_skills(&skills); + for (category, category_skills) in categories { + prompt.push_str(&format!("### {}\n", category)); + for skill in category_skills { + prompt.push_str(&format!( + "- **{}**: {}", + skill.id.as_str(), + skill.description + )); + prompt.push('\n'); + } prompt.push('\n'); } - prompt.push('\n'); - } - prompt.push_str("### When to use skills:\n"); - prompt.push_str("- **IMPORTANT**: You should autonomously decide when to use skills based on your understanding of the user's intent.\n"); - prompt.push_str("- Do not wait for explicit skill names - recognize the need and act.\n"); - prompt.push_str("- Match user's request to the most appropriate skill's domain.\n"); - prompt.push_str("- If multiple skills could apply, choose the most specialized one.\n\n"); - prompt.push_str("### Example:\n"); - prompt.push_str("User: \"分析腾讯财报\" → Intent: Financial analysis → Call: execute_skill(\"finance-tracker\", {...})\n"); + prompt.push_str("### When to use skills:\n"); + prompt.push_str("- **IMPORTANT**: You should autonomously decide when to use skills based on your understanding of the user's intent.\n"); + prompt.push_str("- Do not wait for explicit skill names - recognize the need and act.\n"); + prompt.push_str("- Match user's request to the most appropriate skill's domain.\n\n"); + prompt.push_str("### Example:\n"); + prompt.push_str("User: \"分析腾讯财报\" → Intent: Financial analysis → Call: execute_skill(\"finance-tracker\", {...})\n"); + } } // Sub-agent delegation instructions (Ultra mode only)