Repository navigation
feat: respect disable-model-invocation in SKILL.md frontmatter - #40609
simonedstrom96 wants to merge 1 commit into
Conversation
Skills that set `disable-model-invocation: true` stay installed and manually invocable, but are no longer advertised to the model or loadable through the `skill` tool. - Add optional `disableModelInvocation` to the v1 and `SkillV2.Info` HTTP payloads and generated SDK skill lists, parsed from `disable-model-invocation` in `SKILL.md` frontmatter. - Omit flagged skills from the system prompt / skill guidance and reject them from the model-facing `skill` tool; they stay listed so users can still invoke them as slash commands. - No durable data or migration is affected; the field is optional and unset for existing skills. Closes anomalyco#34498
57180c1 to
94cdf50
Compare
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
|
Does this cover OpenCode v2 approach by extending support? I don’t see relevant part regarding metadata. |
|
Does this also cover |
|
@simonedstrom96 are you still working on this? |
|
I implemented the same change locally and verified it end-to-end. Two notes that might be useful: Filtering the list isn't enough on its own. Measured on a config with 122 skills, 19 of them flagged: Plugins that register their own |
|
This branch has been upgraded to V2. We're no longer taking PRs for V1. If you think this is still relevant, please port it over and open it for V2. — from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊 |
Issue for this PR
Closes #34498
Type of change
What does this PR do?
Skills are always advertised to the model today, so a big manual-only skill costs context on every request even if you only ever run it yourself.
This adds support for
disable-model-invocation: trueinSKILL.mdfrontmatter, which Claude Code and Cursor already use for the same purpose.A skill with the flag is still discovered and still runs as
/skill-name, but it is left out of<available_skills>and theskilltool refuses to load it.That is the whole behavior change: discovery is untouched, only the two model-facing paths filter on the flag.
There are two skill implementations in the tree right now, so the flag is handled in both:
packages/opencode/src/skill/index.ts, filtered out ofSkill.available()(which feeds the system prompt), rejected inpackages/opencode/src/tool/skill.ts.packages/core/src/skill.ts, filtered out ofSkillV2.available()(which feeds skill guidance), rejected inpackages/core/src/tool/skill.ts.Manual invocation keeps working because commands are built from
skill.all()/skill.list(), which still contain the flagged skills.The flag is surfaced as an optional
disableModelInvocationfield on the skill payload, so the generated SDK files andpackages/sdk/openapi.jsonare regenerated (bun run generateinpackages/client, then./script/generate.ts), and I added an entry tospecs/v2/schema-changelog.mdsince that file asks for generated SDK schema changes to be recorded.Docs for the new field are in
packages/web/src/content/docs/skills.mdx.How did you verify your code works?
Tests added:
packages/opencode/test/skill/skill.test.ts: a flagged skill shows up inall()but not inavailable().packages/opencode/test/tool/skill.test.ts: the v1skilltool fails on a flagged skill.packages/core/test/skill.test.tsandtest/skill/guidance.test.ts: flagged skill is listed but excluded fromavailable()and from rendered guidance.packages/core/test/tool-skill.test.ts: the v2skilltool returns "Unable to load skill".bun testpasses inpackages/core(the two failingSnapshot/Git treestests also fail on a cleandevcheckout) and for the skill tests inpackages/opencode.bun typecheckis clean.To reproduce by hand, create
.opencode/skill/manual-only/SKILL.md:opencode debug skilllists it with"disableModelInvocation": true, it is gone from the skills section of the system prompt, and/manual-onlystill inserts the skill content.Screenshots / recordings
Not a UI change.
Checklist