Feature request: declarative `requires:` and `skill-allowlist:` so subagents can lazy-load only the skills they need
Problem
When the parent session spawns a subagent (Agent tool, agent-team workflows, etc.), the subagent inherits the parent's full skill registry and tool catalog as context, even when the agent definition's Tools: whitelist is narrow.
This eager broadcast is conservative-by-default — the loader assumes any skill might be invoked transitively — but the cost compounds:
- The skill-list text is on the order of tens of kilobytes (grows with every new skill the user installs)
- It is injected on every subagent spawn
- For workflows that fan out into many parallel subagents (multi-agent forge runs, kickoff discovery waves, parallel test/review passes), this dominates the per-spawn token bill
There is no way for an agent or skill author to tell the loader "this agent only uses these skills" or "this skill only invokes these other skills". The system has no declarative dependency surface, so it cannot lazy-load.
Proposed surface
Add two optional frontmatter fields:
- Skill frontmatter gains an optional
requires:field listing other skills (e.g./git:create-pr) and tools (e.g.Bash,Read,AskUserQuestion) the skill genuinely invokes. - Agent frontmatter gains an optional
skill-allowlist:field listing which skills the agent is permitted to invoke.
Loader behaviour changes:
- On subagent spawn, inject only skills listed in
skill-allowlist. If the field is absent, fall back to the closure of skills the parent context has actually used in this session (or fall back to current behaviour for backward compatibility — see below). - On skill invocation, walk the
requires:graph to ensure transitively-needed skills are loaded. - Skills NOT in the closure are referenced by name only (no body); the agent can request a load on demand via a tool call or implicit trigger.
Why declarative over discovery
A discovery-based alternative — "the loader scans skill bodies for /namespace:name references and builds the graph automatically" — is appealing but fragile:
- Skills compose dynamically. An
AskUserQuestionbranch may invoke different skills based on the user's choice; static analysis cannot resolve which are actually reachable. - String-grep for
/namespace:nameproduces false positives in prose, examples, and forbidden-pattern tables. A skill that mentions/git:create-pronly to forbid its direct use would still pull it into the closure. - Authors lose control over what counts as a dependency.
Declarative requires: is explicit, reviewable, and enforceable by author-side audit tooling (which is how schema fields are typically validated in skill ecosystems already).
Backward compatibility
- Skills without
requires:keep the current eager-broadcast behaviour. No regression. - Agents without
skill-allowlist:keep the current full-registry behaviour. No regression. - Migration is opt-in. High-traffic skills and agents (those that fan out into many subagents) declare first; the long tail follows over time.
Why this is distinct from a memory-injection hook
A separate request (PreMemoryLoad hook) addresses rule dual-injection from worktree symlink resolution. This request addresses skill / tool catalog eager broadcast at subagent spawn. The two share an architectural family — loader-side cost reduction — but the surfaces and fixes are different:
| Dimension | Memory-loader hook | This request |
|---|---|---|
| What is over-injected | Rule files | Skill registry + tool catalog |
| When | Session start + every memory refresh | Every subagent spawn |
| Trigger | Symlink → dual realpath resolution | Conservative "any skill might be needed" default |
| Fix shape | Pre-injection hook + content-hash dedup | Declarative requires: + skill-allowlist: + lazy load |
Filing both separately because the surfaces are distinct.
Acceptance criteria
- Skill frontmatter
requires:field accepts a list of/namespace:namestrings and tool names. - Agent frontmatter
skill-allowlist:field accepts a list of/namespace:namestrings. - On subagent spawn, the loader injects only skills resolvable from
skill-allowlist(transitively closed viarequires:). - Absence of either field reproduces today's behaviour.
- A subagent attempting to invoke a skill not in its closure receives a clear error or a load-on-demand path (implementation detail).
---
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗