You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**Priority:** HIGH -- the current implementation defeats its own purpose and will not scale for multi-agent workflows.
398
-
399
-
**Depends on:** None (can be built in parallel with other features).
400
-
401
-
**Current state and problems:**
402
-
403
-
The skills system exists (Feature "Agent Skills" in Existing Features) but has several design flaws that contradict the intended purpose of skills and will become blockers as multi-agent workflows add more domain-specific skills:
404
-
405
-
1.**Full skill body always injected into context** (`base_agent.py:774-784`). Every selected skill has its entire `instructions` field dumped into the system prompt via `_SKILL_ENTRY_TEMPLATE`. There is no progressive disclosure -- if 5 skills are selected, all 5 bodies go in at once. The YAML frontmatter (name, description) was designed for lightweight selection, but selection immediately triggers full injection. This directly contradicts the reference pattern from [anthropics/skills](https://github.com/anthropics/skills/blob/main/skills/skill-creator/SKILL.md), which specifies three loading levels:
- Level 3: **Bundled resources** -- loaded as needed (unlimited, scripts execute without loading)
409
-
410
-
2.**No bundled resources support**. `_parse_skill_file` (`base_agent.py:264-308`) only reads the single SKILL.md file. The reference pattern describes `scripts/`, `references/`, `assets/` directories alongside SKILL.md. A skill like `ontology-mapping` may need reference docs (OWL specs, mapping examples) and template scripts (Cypher export patterns) that should load on demand -- not bloat the system prompt or be absent entirely.
411
-
412
-
3.**No context budget awareness**. Skills are injected unconditionally into the system prompt. In multi-agent workflows where each specialist agent may need 2-3 domain skills, unbounded injection will collide with Feature 5 (Context Window Management).
413
-
414
-
4.**Retriever makes all-or-nothing decisions**. At `base_agent.py:1034-1038`, the retriever selects skills based on `{name, description}` -- appropriate for lightweight triage. But selection immediately injects the full body. There is no intermediate step where the agent could inspect a skill summary before committing to loading the full instructions.
415
-
416
-
5.**`tools` field is purely decorative** (`resources.py:347`). `Skill.tools` is shown in the prompt but never used functionally -- it doesn't filter available tools, validate that referenced tools exist, or influence retriever decisions.
417
-
418
-
6.**No skill directory tracking**. `source_path` stores the SKILL.md file path, but nothing records the parent directory. Even if bundled resources existed, the system wouldn't know where to find `references/` or `scripts/` relative to the skill.
419
-
420
-
7.**Loading is wasteful for multi-agent**. `configure()` loads ALL skills from `skills_directory` via glob, then `spec.skill_names` filters via `select_skills_by_names()`. In BaseAgent multi-agent workflows, each agent needs 1-3 skills from a shared pool. Loading all skills just to discard most of them is unnecessary overhead and risks cross-agent state confusion.
421
-
422
-
**Skill directory convention:**
423
-
424
-
Skills reside in a conventional directory structure under the project root:
425
-
426
-
```
427
-
skills/ # skills_directory points here
428
-
ontology-design/
429
-
SKILL.md # required: YAML frontmatter + markdown body
430
-
references/ # optional: bundled reference docs
431
-
owl_spec.md
432
-
scripts/ # optional: bundled template scripts
433
-
template.py
434
-
database-evaluation/
435
-
SKILL.md
436
-
parser-development/
437
-
SKILL.md
438
-
scripts/
439
-
csv_template.py
440
-
ontology-mapping/
441
-
SKILL.md
442
-
references/
443
-
owl_mapping_guide.md
444
-
memgraph-export/
445
-
SKILL.md
446
-
scripts/
447
-
cypher_template.py
448
-
```
449
-
450
-
`AgentSpec.skill_names=["ontology-design"]` resolves to `{skills_directory}/ontology-design/SKILL.md`. Each agent loads **only** the skills specified in its spec -- no glob, no load-all-then-filter.
451
-
452
-
**Phase 1 -- Model cleanup: remove `trigger`, add `source_dir`**
453
-
454
-
Remove `trigger` from the `Skill` model and all code that branches on it:
455
-
456
-
-`resources.py:344` -- remove `trigger` field from `Skill`
457
-
-`resource_manager.py:526-532` -- remove `trigger="manual"` guard; all skills follow the same selection logic
458
-
-`base_agent.py:1033-1037` -- retriever passes all skills as candidates (no trigger filter)
Add `source_dir: str | None` to the `Skill` model. When loading from a file, set `source_dir` to the SKILL.md's parent directory. Add a `has_bundled_resources` computed property that checks for `references/`, `scripts/`, or `assets/` subdirectories.
463
-
464
-
```python
465
-
# In resources.py, add to Skill:
466
-
source_dir: Optional[str] = Field(None, description="Directory containing the SKILL.md and optional bundled resources")
467
-
468
-
@property
469
-
defhas_bundled_resources(self) -> bool:
470
-
ifnotself.source_dir:
471
-
returnFalse
472
-
d = Path(self.source_dir)
473
-
returnany((d / sub).is_dir() for sub in ("references", "scripts", "assets"))
Replace the current "load all → filter" loading model with targeted loading. Each agent loads only the skills specified in its `AgentSpec.skill_names` directly from their conventional directory paths.
500
-
501
-
Add `_resolve_skill_path(skill_name) -> Path | None` to `BaseAgent`:
The `select_skills_by_names()` call is removed from `configure()` -- since we only loaded the skills we need, there is nothing to filter. `load_skills()` and `add_skill()` remain as public API for ad-hoc single-agent usage.
This is the core behavioral change. The system prompt shows only skill metadata at configuration time; the `retrieve` node loads full bodies on demand when the task arrives.
-`configure()` / `_generate_system_prompt(is_retrieval=False)`: injects only the **skill catalog** -- name, description, and bundled resource manifest per skill (~2-3 lines each)
554
-
-`retrieve` node: always runs skill selection (even if `use_tool_retriever=False`), then regenerates system prompt with full instructions for selected skills
555
-
- The agent sees full instructions only for task-relevant skills
556
-
557
-
When `skill_retrieval=False`:
558
-
- Falls back to current behavior: all loaded skills' full instructions injected into the system prompt at configure time
559
-
- Provided as an escape hatch for simple single-skill setups
560
-
561
-
**New prompt templates** in `prompts.py`:
562
-
563
-
```python
564
-
_SKILL_CATALOG_SECTION= \
565
-
"""
566
-
567
-
AVAILABLE SKILLS
568
-
===============================
569
-
The following skills provide specialized domain knowledge and workflows.
570
-
Relevant skill instructions will be loaded based on the current task.
The retrieve node is no longer a no-op when `use_tool_retriever=False` -- it always processes skill retrieval when `skill_retrieval=True` and there are registered skills.
678
-
679
-
**Files to modify (Phase 3):**
680
-
-`BaseAgent/config.py` -- `skill_retrieval: bool = True` field + env var override
681
-
-`BaseAgent/prompts.py` -- `_SKILL_CATALOG_SECTION`, `_SKILL_CATALOG_ENTRY`, `_SKILL_SELECTION_PROMPT` (new templates)
682
-
-`BaseAgent/base_agent.py` -- `_generate_system_prompt()` (catalog vs. full injection), `_select_skills_for_prompt()` (new method), `configure()` (store `self.skill_retrieval`)
-`BaseAgent/tests/test_skills.py` -- progressive disclosure tests (catalog in initial prompt, full body after retrieval)
685
-
686
-
**Phase 4 -- Bundled resource access via REPL**
687
-
688
-
Register a built-in helper function `read_skill_resource(skill_name, path)` that reads files from a skill's bundled resource directory. This lets the agent load reference docs and templates on demand from within `<execute>` blocks:
689
-
690
-
```python
691
-
# Injected into REPL namespace when skills with bundled resources are present
raiseFileNotFoundError(f"Skill '{skill_name}' not found or has no source directory")
704
-
full_path = Path(skill.source_dir) / path
705
-
ifnot full_path.is_file():
706
-
raiseFileNotFoundError(f"Resource '{path}' not found in skill '{skill_name}'")
707
-
return full_path.read_text(encoding="utf-8")
708
-
```
709
-
710
-
Injected into the per-instance REPL namespace via `functools.partial(_agent=self)` in `_inject_custom_functions_to_repl()` when any loaded skill has bundled resources.
711
-
712
-
The skill instructions would then say things like:
- At `configure()` time, validate that all tools listed in `skill.tools` actually exist in `ResourceManager`. Emit a warning for missing tools.
728
-
- When a skill is selected by the retriever in `_select_skills_for_prompt()`, auto-select its referenced tools (even if the retriever didn't explicitly pick them). This ensures skills always have their required tools available.
-`skill_retrieval=False`: restores current all-in body injection behavior
737
-
-`add_skill()` and `load_skills()` remain as public API for ad-hoc usage
738
-
- Default (`skill_retrieval=True`) changes the prompt behavior but is strictly better -- agents see the same skill instructions, just loaded on demand rather than always present
739
-
740
-
---
741
-
742
395
## Post-Prototype Feature Specifications
743
396
744
397
Deferred until the prototype is validated. Listed here to inform design decisions -- do not build hooks or abstractions for these unless they are zero-cost.
@@ -817,14 +470,6 @@ New files to be created by future features:
817
470
818
471
```
819
472
Depends On Effort
820
-
== GROUP A (parallel, no dependencies) =============================================
821
-
Feature 10 Skills system overhaul -- ~3 days
822
-
Phase 1 Model cleanup (remove trigger, add source_dir) ~0.5 day
823
-
Phase 2 Spec-driven targeted skill loading ~0.5 day
824
-
Phase 3 Progressive disclosure in prompt injection ~1 day
825
-
Phase 4 Bundled resource access via REPL ~0.5 day
826
-
Phase 5 Functional tools field ~0.5 day
827
-
828
473
== GROUP B (after Group A completes) ===============================================
0 commit comments