fix(skills): inject skill prompts and tools into agent system prompt

Skill prompts and tool definitions from SKILL.toml were parsed and stored
correctly but never included in the agent's system prompt. Both prompt-building
paths (channels/mod.rs and agent/prompt.rs) only emitted skill metadata (name,
description, location), telling the LLM to "read" the SKILL.toml on demand.
This caused the agent to attempt manual file reads that often failed, leaving
skills effectively ignored.

Now both paths inline <instructions> and <tools> blocks inside each <skill>
XML element, so the agent receives full skill context without extra tool calls.

Closes #877

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Edvard 2026-02-18 22:50:35 -05:00 committed by Chummy
parent 14fb3fbcae
commit 8a4da141d6
2 changed files with 69 additions and 15 deletions

View file

@ -165,13 +165,35 @@ impl PromptSection for SkillsSection {
.join(&skill.name)
.join("SKILL.md")
});
let _ = writeln!(prompt, " <skill>");
let _ = writeln!(prompt, " <name>{}</name>", skill.name);
let _ = writeln!(
prompt,
" <skill>\n <name>{}</name>\n <description>{}</description>\n <location>{}</location>\n </skill>",
skill.name,
skill.description,
location.display()
" <description>{}</description>",
skill.description
);
let _ = writeln!(prompt, " <location>{}</location>", location.display());
if !skill.tools.is_empty() {
let _ = writeln!(prompt, " <tools>");
for tool in &skill.tools {
let _ = writeln!(
prompt,
" <tool name=\"{}\" kind=\"{}\">{}</tool>",
tool.name, tool.kind, tool.description
);
}
let _ = writeln!(prompt, " </tools>");
}
if !skill.prompts.is_empty() {
let _ = writeln!(prompt, " <instructions>");
for p in &skill.prompts {
prompt.push_str(" ");
prompt.push_str(p);
prompt.push('\n');
}
let _ = writeln!(prompt, " </instructions>");
}
let _ = writeln!(prompt, " </skill>");
}
prompt.push_str("</available_skills>");
Ok(prompt)