🏠 Home ← Docs Index
Open Beta 📖 Interactive Reader Raw .md llms.txt

Skills: the gate

Read this before changing skill_gate.go, skill_scanner.go, skill_text_view.go, skill_quality.go, or a way a skill reaches GoClaw.

A skill's text goes into the system prompt, ahead of the history, so it speaks with the agent's own authority. The gate is the one security check for a skill, however it got here. Each way in is an adapter over it, as a provider is over the agent loop, and skill_gate_conformance_test.go runs one set of skills through all of them.

Way in Check When On a block
Dashboard verify / save EvaluateSkillContentQuality → inspectSkillText, then a model before the write not saved, unless an admin accepts this text (the hash field of the save)
Dashboard install (github:) InstallSkillFromSource → inspectSkillText before the write not written, logged
CLI skills install / add scanInstalledSkill → ScanSkillDir after the copy removed; --force keeps it on disk
Plugin skill, workspace/skills, a hand edit, a git pull LoadSkillsForContext → gateSkills every load stays out of the prompt, logged once

Every skill passes the last row, whichever row it came in by: it is the backstop for a file that changed after it was checked. It drops a skill before selection, so a blocked skill wins no place in FilterSkillsFor or keepSessionSkills, and one that turned bad mid-session is gone from the next turn. LoadSkills is the full list, for the admin's views (Skills page, skills list, skills scan); nothing that builds a prompt may read it.

The verdict

SkillVerdict is safe, caution or block, and it is not the quality score:

What the scanner reads

Before tightening a rule to critical, remember it is enforced at load. Run it over skills-registry/ and the built-in skills (TestBuiltinSkillsPassTheGate fails on a built-in), and prefer warn where a real skill could say the same thing.

An acceptance

skills.accepted in config.yaml maps a skill's name to the hash of the text an admin read (AcceptSkill). It is in config.yaml because no tool of the agent writes there. The hash (skillContentHash) covers the text, the description and the tags: any change voids it, as it does a plugin item's approval. The dashboard sends the hash the page showed, so nothing changed meanwhile is accepted unseen. skills.gate: warn turns the block at load into a log line, for a first rollout. SkillSecurity.Withheld is what all of it comes to: models do not get this skill.