- Runtime + filesystem skill runtime implementation for "AgentSkills" in Go.
- An "AgentSkill" is a directory/location containing a
SKILL.mdfile with YAML frontmatter. Full specification at the official site. - The tools are implemented using the specification and data types provided in llmtools-go repo.
-
A runtime that hosts a catalog of skills and manages session-scoped active skills.
-
Progressive disclosure:
- the catalog exposes metadata only
- a session "loads" a skill to disclose its full
SKILL.mdbody into the prompt
-
A provider abstraction (
spec.SkillProvider) and a hardened reference provider:providers/fsskillprovider: skills backed by a local filesystem directory
-
Tool wiring via
llmtools-go:skills.load,skills.unload,skills.readresource,skills.runscript- A runtime prompt API
Runtime.SkillsPromptXML(...)which can emit:<availableSkills>...</availableSkills><activeSkills>...</activeSkills>- or a wrapper
<skillsPrompt>...</skillsPrompt>when both are requested.
-
Create a runtime with the filesystem provider
fsp, _ := fsskillprovider.New() // RunScript disabled by default rt, _ := agentskills.New( agentskills.WithProvider(fsp), )
-
Add a skill to the catalog
rec, err := rt.AddSkill(ctx, spec.SkillDef{ Type: "fs", Name: "hello-skill", // This is base dir containing SKILL.md for "hello-skill". // Typically, base dir name and skill name should match. Location: "/abs/path/to/hello-skill", }) _ = rec _ = err
-
Build the “available skills” prompt XML (metadata only)
xml, _ := rt.SkillsPromptXML(ctx, &agentskills.SkillFilter{ Activity: spec.SkillActivityInactive, // with no SessionID: treated as "all skills" }) // <availableSkills> ... </availableSkills>
-
Create a session with initial active skills (progressive disclosure)
sid, active, err := rt.NewSession(ctx, agentskills.WithSessionActiveSkills([]spec.SkillDef{rec.Def}), ) _ = sid _ = active // []spec.SkillDef _ = err
-
Build “active skills” prompt XML
activeXML, _ := rt.SkillsPromptXML(ctx, &agentskills.SkillFilter{ SessionID: sid, Activity: spec.SkillActivityActive, }) // <activeSkills> // <skill name="hello-skill"><![CDATA[ ... SKILL.md body ... ]]></skill> // </activeSkills>
-
Build a combined prompt (active + available/inactive) for a session
xml, _ := rt.SkillsPromptXML(ctx, &agentskills.SkillFilter{ SessionID: sid, Activity: spec.SkillActivityAny, }) // <skillsPrompt> // <availableSkills>...</availableSkills> // <activeSkills>...</activeSkills> // </skillsPrompt>
-
Create a tool registry for an LLM session
reg, _ := rt.NewSessionRegistry(ctx, sid) // Registry includes: skills.load / skills.unload / skills.readresource / skills.runscript _ = reg
The FS provider is intentionally thin and delegates most sandboxing/hardening to llmtools-go:
skills.readresourceusesllmtools-go/fstooland is scoped to the skill root via:allowedRoots = [skillRoot]workBaseDir = skillRoot
skills.runscriptusesllmtools-go/exectooland is scoped similarlyRunScriptis disabled by default; enable explicitly viafsskillprovider.WithRunScripts(true)
Working end-to-end examples live in:
- fs test
- Demonstrates: create runtime, add skill, list/prompt, create session with initial actives, run tools.
- Formatting follows
gofumptandgolinesviagolangci-lint. Rules are in .golangci.yml. - Useful scripts are defined in
taskfile.yml; requires Task. - Bug reports and PRs are welcome:
- Keep the public API small and intentional.
- Avoid leaking provider‑specific types through the public surface; put them under
internal/. - Please run tests and linters before sending a PR.
Copyright (c) 2026 - Present - Pankaj Pipada
All source code in this repository, unless otherwise noted, is licensed under the MIT License. See LICENSE for details.