feat(core): improve activate_skill tool and use lowercase XML tags (#16009)

This commit is contained in:
N. Taylor Mullen
2026-01-06 17:10:00 -08:00
committed by GitHub
parent 59a18e710d
commit da85e3f8f2
4 changed files with 30 additions and 18 deletions

View File

@@ -521,7 +521,7 @@ exports[`Core System Prompt (prompts.ts) > should include available_skills when
- **Confirm Ambiguity/Expansion:** Do not take significant actions beyond the clear scope of the request without confirming with the user. If asked *how* to do something, explain first, don't just do it.
- **Explaining Changes:** After completing a code modification or file operation *do not* provide summaries unless asked.
- **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes.
- **Skill Guidance:** Once a skill is activated via \`activate_skill\`, its instructions and resources are returned wrapped in \`<ACTIVATED_SKILL>\` tags. You MUST treat the content within \`<INSTRUCTIONS>\` as expert procedural guidance, prioritizing these specialized rules and workflows over your general defaults for the duration of the task. You may utilize any listed \`<AVAILABLE_RESOURCES>\` as needed. Follow this expert guidance strictly while continuing to uphold your core safety and security standards.
- **Skill Guidance:** Once a skill is activated via \`activate_skill\`, its instructions and resources are returned wrapped in \`<activated_skill>\` tags. You MUST treat the content within \`<instructions>\` as expert procedural guidance, prioritizing these specialized rules and workflows over your general defaults for the duration of the task. You may utilize any listed \`<available_resources>\` as needed. Follow this expert guidance strictly while continuing to uphold your core safety and security standards.
Mock Agent Directory
# Available Agent Skills

View File

@@ -175,7 +175,7 @@ ${skillsXml}
- **Do Not revert changes:** Do not revert changes to the codebase unless asked to do so by the user. Only revert changes made by you if they have resulted in an error or if the user has explicitly asked you to revert the changes.${
skills.length > 0
? `
- **Skill Guidance:** Once a skill is activated via \`${ACTIVATE_SKILL_TOOL_NAME}\`, its instructions and resources are returned wrapped in \`<ACTIVATED_SKILL>\` tags. You MUST treat the content within \`<INSTRUCTIONS>\` as expert procedural guidance, prioritizing these specialized rules and workflows over your general defaults for the duration of the task. You may utilize any listed \`<AVAILABLE_RESOURCES>\` as needed. Follow this expert guidance strictly while continuing to uphold your core safety and security standards.`
- **Skill Guidance:** Once a skill is activated via \`${ACTIVATE_SKILL_TOOL_NAME}\`, its instructions and resources are returned wrapped in \`<activated_skill>\` tags. You MUST treat the content within \`<instructions>\` as expert procedural guidance, prioritizing these specialized rules and workflows over your general defaults for the duration of the task. You may utilize any listed \`<available_resources>\` as needed. Follow this expert guidance strictly while continuing to uphold your core safety and security standards.`
: ''
}${mandatesVariant}${
!interactiveMode

View File

@@ -87,14 +87,14 @@ describe('ActivateSkillTool', () => {
expect(mockConfig.getWorkspaceContext().addDirectory).toHaveBeenCalledWith(
'/path/to/test-skill',
);
expect(result.llmContent).toContain('<ACTIVATED_SKILL name="test-skill">');
expect(result.llmContent).toContain('<INSTRUCTIONS>');
expect(result.llmContent).toContain('<activated_skill name="test-skill">');
expect(result.llmContent).toContain('<instructions>');
expect(result.llmContent).toContain('Skill instructions content.');
expect(result.llmContent).toContain('</INSTRUCTIONS>');
expect(result.llmContent).toContain('<AVAILABLE_RESOURCES>');
expect(result.llmContent).toContain('</instructions>');
expect(result.llmContent).toContain('<available_resources>');
expect(result.llmContent).toContain('Mock folder structure');
expect(result.llmContent).toContain('</AVAILABLE_RESOURCES>');
expect(result.llmContent).toContain('</ACTIVATED_SKILL>');
expect(result.llmContent).toContain('</available_resources>');
expect(result.llmContent).toContain('</activated_skill>');
expect(result.returnDisplay).toContain('Skill **test-skill** activated');
expect(result.returnDisplay).toContain('Mock folder structure');
});

View File

@@ -18,6 +18,7 @@ import type {
import { BaseDeclarativeTool, BaseToolInvocation, Kind } from './tools.js';
import type { Config } from '../config/config.js';
import { ACTIVATE_SKILL_TOOL_NAME } from './tool-names.js';
import { ToolErrorType } from './tool-error.js';
/**
* Parameters for the ActivateSkill tool
@@ -51,7 +52,7 @@ class ActivateSkillToolInvocation extends BaseToolInvocation<
if (skill) {
return `"${skillName}": ${skill.description}`;
}
return `"${skillName}" (⚠️ unknown skill)`;
return `"${skillName}" (?) unknown skill`;
}
private async getOrFetchFolderStructure(
@@ -107,9 +108,15 @@ ${folderStructure}`,
if (!skill) {
const skills = skillManager.getSkills();
const availableSkills = skills.map((s) => s.name).join(', ');
const errorMessage = `Skill "${skillName}" not found. Available skills are: ${availableSkills}`;
return {
llmContent: `Error: Skill "${skillName}" not found. Available skills are: ${skills.map((s) => s.name).join(', ')}`,
returnDisplay: `Skill "${skillName}" not found.`,
llmContent: `Error: ${errorMessage}`,
returnDisplay: `Error: ${errorMessage}`,
error: {
message: errorMessage,
type: ToolErrorType.INVALID_TOOL_PARAMS,
},
};
}
@@ -126,15 +133,15 @@ ${folderStructure}`,
);
return {
llmContent: `<ACTIVATED_SKILL name="${skillName}">
<INSTRUCTIONS>
llmContent: `<activated_skill name="${skillName}">
<instructions>
${skill.body}
</INSTRUCTIONS>
</instructions>
<AVAILABLE_RESOURCES>
<available_resources>
${folderStructure}
</AVAILABLE_RESOURCES>
</ACTIVATED_SKILL>`,
</available_resources>
</activated_skill>`,
returnDisplay: `Skill **${skillName}** activated. Resources loaded from \`${path.dirname(skill.location)}\`:\n\n${folderStructure}`,
};
}
@@ -169,10 +176,15 @@ export class ActivateSkillTool extends BaseDeclarativeTool<
});
}
const availableSkillsHint =
skillNames.length > 0
? ` (Available: ${skillNames.map((n) => `'${n}'`).join(', ')})`
: '';
super(
ActivateSkillTool.Name,
'Activate Skill',
"Activates a specialized agent skill by name. Returns the skill's instructions wrapped in `<ACTIVATED_SKILL>` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description.",
`Activates a specialized agent skill by name${availableSkillsHint}. Returns the skill's instructions wrapped in \`<activated_skill>\` tags. These provide specialized guidance for the current task. Use this when you identify a task that matches a skill's description. ONLY use names exactly as they appear in the \`<available_skills>\` section.`,
Kind.Other,
zodToJsonSchema(schema),
messageBus,