Class: Clacky::Tools::InvokeSkill
- Defined in:
- lib/clacky/tools/invoke_skill.rb
Overview
Tool for invoking skills within the agent This allows the AI to call skills as tools rather than requiring explicit user commands
Instance Method Summary collapse
-
#execute(skill_name:, task:, agent: nil, skill_loader: nil, working_dir: nil) ⇒ Hash
Execute the skill invocation.
-
#format_call(args) ⇒ String
Format the tool call for display.
-
#format_result(result) ⇒ String
Format the tool result for display.
Methods inherited from Base
#category, #description, #name, #parameters, #to_function_definition
Instance Method Details
#execute(skill_name:, task:, agent: nil, skill_loader: nil, working_dir: nil) ⇒ Hash
Execute the skill invocation
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/clacky/tools/invoke_skill.rb', line 32 def execute(skill_name:, task:, agent: nil, skill_loader: nil, working_dir: nil) # Validate injected dependencies return { error: "Agent context is required" } unless agent return { error: "Skill loader is required" } unless skill_loader # Find skill by name skill = skill_loader.find_by_name(skill_name) return { error: "Skill not found: #{skill_name}" } unless skill # Execute skill based on its configuration. # Note: disable-model-invocation only prevents the skill from appearing in AVAILABLE SKILLS # (so the model won't auto-discover it). It does NOT block execution here — the user may # have triggered this skill explicitly via a slash command (/skill-name). if skill.fork_agent? # Execute in isolated subagent result = agent.send(:execute_skill_with_subagent, skill, task) { message: "Skill '#{skill_name}' executed in subagent", result: result, skill_type: "subagent" } else # Deferred injection path: enqueue the skill inject on the agent. # # Injecting inside execute() would produce an illegal message ordering for Bedrock: # assistant: {toolUse: invoke_skill} # assistant: {text: skill_instructions} ← injected here (breaks pairing) # user: {toolResult: invoke_skill} ← observe() appends this too late # # Instead, enqueue the injection so the agent loop can flush it AFTER observe() # appends the toolResult, producing the correct sequence: # assistant: {toolUse: invoke_skill} # user: {toolResult: ...} ← observe() appends first # assistant: {text: skill_instructions} ← flush_pending_injections runs here # user: "[SYSTEM] please proceed" agent.enqueue_injection(skill, task) "Skill '#{skill_name}' instructions expanded. Proceed to execute the task." end end |
#format_call(args) ⇒ String
Format the tool call for display
75 76 77 78 |
# File 'lib/clacky/tools/invoke_skill.rb', line 75 def format_call(args) skill = args[:skill_name] || args["skill_name"] "InvokeSkill(#{skill})" end |
#format_result(result) ⇒ String
Format the tool result for display
83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/clacky/tools/invoke_skill.rb', line 83 def format_result(result) if result.is_a?(String) result elsif result[:error] "Error: #{result[:error]}" elsif result[:skill_type] == "subagent" "Subagent executed successfully" else "Skill content expanded" end end |