feat(skill-execution): implement execute_skill tool with full execution chain
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled

- Add ExecuteSkillTool for LLM to call skills during conversation
- Implement SkillExecutor trait in Kernel for skill execution
- Update AgentLoop to support tool execution with skill_executor
- Add default skills_dir configuration in KernelConfig
- Connect frontend skillMarketStore to backend skill_list command
- Update technical documentation with Skill system architecture

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-24 13:24:23 +08:00
parent 1441f98c5e
commit 504d5746aa
8 changed files with 698 additions and 131 deletions

View File

@@ -4,13 +4,15 @@ mod file_read;
mod file_write;
mod shell_exec;
mod web_fetch;
mod execute_skill;
pub use file_read::FileReadTool;
pub use file_write::FileWriteTool;
pub use shell_exec::ShellExecTool;
pub use web_fetch::WebFetchTool;
pub use execute_skill::ExecuteSkillTool;
use crate::tool::{ToolRegistry, Tool};
use crate::tool::ToolRegistry;
/// Register all built-in tools
pub fn register_builtin_tools(registry: &mut ToolRegistry) {
@@ -18,4 +20,5 @@ pub fn register_builtin_tools(registry: &mut ToolRegistry) {
registry.register(Box::new(FileWriteTool::new()));
registry.register(Box::new(ShellExecTool::new()));
registry.register(Box::new(WebFetchTool::new()));
registry.register(Box::new(ExecuteSkillTool::new()));
}

View File

@@ -0,0 +1,72 @@
//! Execute skill tool
use async_trait::async_trait;
use serde_json::{json, Value};
use zclaw_types::{Result, ZclawError};
use crate::tool::{Tool, ToolContext};
pub struct ExecuteSkillTool;
impl ExecuteSkillTool {
pub fn new() -> Self {
Self
}
}
#[async_trait]
impl Tool for ExecuteSkillTool {
fn name(&self) -> &str {
"execute_skill"
}
fn description(&self) -> &str {
"Execute a skill by its ID. Skills are predefined capabilities that can be invoked with structured input."
}
fn input_schema(&self) -> Value {
json!({
"type": "object",
"properties": {
"skill_id": {
"type": "string",
"description": "The ID of the skill to execute"
},
"input": {
"type": "object",
"description": "The input parameters for the skill",
"additionalProperties": true
}
},
"required": ["skill_id"]
})
}
async fn execute(&self, input: Value, context: &ToolContext) -> Result<Value> {
let skill_id = input["skill_id"].as_str()
.ok_or_else(|| ZclawError::InvalidInput("Missing 'skill_id' parameter".into()))?;
let skill_input = input.get("input").cloned().unwrap_or(json!({}));
// Get skill executor from context
let executor = context.skill_executor.as_ref()
.ok_or_else(|| ZclawError::ToolError("Skill executor not available".into()))?;
// Get session_id from context or use empty string
let session_id = context.session_id.as_deref().unwrap_or("");
// Execute the skill
executor.execute_skill(
skill_id,
&context.agent_id.to_string(),
session_id,
skill_input,
).await
}
}
impl Default for ExecuteSkillTool {
fn default() -> Self {
Self::new()
}
}