skill loading in extras

3clyp50 committed Feb 5, 2026 at 16:03 UTC 6585d895a903f90cf619eb9a2b3efe7b101223c9
3 files changed +58 -7
prompts/agent.system.skills.loaded.md new
+5
@@ -0,0 +1,5 @@
1 +# Loaded skill
2 +- The following skill was explicitly loaded via skills_tool
3 +- Full content persists here each turn to survive history compression
4 +
5 +{{skills}}
python/extensions/message_loop_prompts_after/_65_include_loaded_skills.py new
+29
@@ -0,0 +1,29 @@
1 +from python.helpers.extension import Extension
2 +from agent import LoopData
3 +
4 +
5 +DATA_NAME_LOADED_SKILL = "loaded_skill"
6 +
7 +
8 +class IncludeLoadedSkills(Extension):
9 + async def execute(self, loop_data: LoopData = LoopData(), **kwargs):
10 + extras = loop_data.extras_persistent
11 +
12 + # Clear previous
13 + if "loaded_skills" in extras:
14 + del extras["loaded_skills"]
15 +
16 + # Get single loaded skill
17 + skill_data = self.agent.data.get(DATA_NAME_LOADED_SKILL)
18 + if not skill_data or not isinstance(skill_data, dict):
19 + return
20 +
21 + content = str(skill_data.get("content") or "").strip()
22 + if not content:
23 + return
24 +
25 + # Inject into extras
26 + extras["loaded_skills"] = self.agent.read_prompt(
27 + "agent.system.skills.loaded.md",
28 + skills=content,
29 + )
python/tools/skills_tool.py
+24 -7
@@ -8,6 +8,9 @@ from python.helpers import projects, files, file_tree
8 from python.helpers import skills as skills_helper, runtime
9
10
11 +DATA_NAME_LOADED_SKILL = "loaded_skill"
12 +
13 +
14 class SkillsTool(Tool):
15 """
16 Manage and use SKILL.md-based Skills (Anthropic open standard).
@@ -106,7 +109,6 @@ class SkillsTool(Tool):
109 return "\n".join(lines)
110
111 def _load(self, skill_name: str) -> str:
109 -
112 skill_name = skill_name.strip()
113 if skill_name.startswith("**") and skill_name.endswith("**"):
114 skill_name = skill_name[
@@ -124,17 +126,32 @@ class SkillsTool(Tool):
126 if not skill:
127 return f"Error: skill not found: {skill_name!r}. Try skills_tool method=list or method=search."
128
127 - # Enumerate files under the skill directory for progressive disclosure
128 - referenced_files = self._list_skill_files(skill.path, max_files=80)
129 - rel_skill_dir = Path(files.deabsolute_path(str(skill.path)))
129 + # Build skill content block
130 + files_tree = self._list_skill_files(skill.path, max_files=80)
131 if self.agent.config.code_exec_ssh_enabled:
132 runtime_path = files.normalize_a0_path(str(skill.path))
133 else:
134 runtime_path = str(skill.path)
135
136 + content_block = self._build_loaded_skill_block(
137 + skill=skill,
138 + runtime_path=runtime_path,
139 + files_tree=files_tree,
140 + )
141 +
142 + # Store single skill in agent.data (replaces previous)
143 + self.agent.data[DATA_NAME_LOADED_SKILL] = {
144 + "name": skill.name,
145 + "content": content_block,
146 + }
147 +
148 + return f"Loaded skill '{skill.name}' into persistent extras."
149 +
150 + def _build_loaded_skill_block(
151 + self, *, skill: skills_helper.Skill, runtime_path: str, files_tree: str
152 + ) -> str:
153 lines: List[str] = []
154 lines.append(f"Skill: {skill.name}")
137 - # lines.append(f"Path: {rel_skill_dir}")
155 lines.append(f"Path: {runtime_path}")
156 if skill.version:
157 lines.append(f"Version: {skill.version}")
@@ -161,11 +178,11 @@ class SkillsTool(Tool):
178 lines.append(skill.content.strip() or "(empty)")
179 lines.append("")
180
164 - if referenced_files:
181 + if files_tree:
182 lines.append(
183 "Files in skill directory (use skills_tool method=read_file to open):"
184 )
168 - lines.append(referenced_files)
185 + lines.append(files_tree)
186 else:
187 lines.append("No additional files found in skill directory.")
188