ScaiSkills
ScaiSkills is the skill framework inside ScaiGrid. You publish a versioned bundle — a manifest plus a SKILL.md body plus optional references — then bind it into a scope (a workspace, a channel, a user, or a Core). When an agent runs, ScaiSkills resolves the bindings for the active scopes and feeds the LLM a compact, progressive-disclosure surface so it only loads the full instructions for the skills it actually decides to use.
Skills are content-addressed: identical bundles dedup on a SHA-256 of the tarball. Versions are semver-ordered and monotonic per skill. Dependencies are resolved eagerly at bind time and frozen in a lockfile on the binding row, so the dependency tree never silently rolls forward underneath a running agent.
When to use it#
- You want reusable instructions, references, and tool wiring that aren't baked into a single bot or Core.
- You want different agents (a ScaiWave channel bot and a ScaiCore autonomous agent) to share the same skill library with the same versioning.
- You need permission and secret approval gating before a skill participates in a turn — supply-chain mitigation against a published version requesting new capabilities.
- You want the LLM to discover skills by description and only pull the body of the one it chose, instead of front-loading every skill in the system prompt.
If you only need a static system prompt for one bot, ScaiBot's tone configuration is enough — you don't need ScaiSkills.
What you get#
- Content-addressed bundles.
.tar.gzuploads dedup on SHA-256. Storage URIs live on the version row. - Strict semver publishing. New versions must be strictly greater than every previously published semver for the skill.
- Scope-based bindings. Bind to
workspace,channel,user, orcore; user > channel > workspace precedence. - Eager dependency resolution. Bind time walks
requires.skills, detects cycles, persists a lockfile on the binding. - Permission and secret gating. Bindings sit in
pending_grantsuntil every declared permission is granted and every required secret is mapped. - Per-scope Redis cache.
POST /resolveis cached for 60 seconds; binding writes invalidate. - Progressive disclosure for the LLM. Three MCP tools —
skills.list,skills.search,skills.view— so models pull skill bodies on demand. - Yank, don't delete. Yanked versions stop being bindable but keep working for existing bindings.
Two-minute mental model#
You manage three nouns and two verbs:
- A Skill is a slug owned by a workspace. It's just an identity.
- A Skill version is a published bundle pinned to a semver under that slug.
- A Binding is one version installed into one scope.
And two verbs:
- You publish versions of a skill into the catalog.
- A runtime resolves the binding set for a scope before each turn.
The catalog is the set of skills your workspace can see (own private plus all public). The binding table is what the runtime actually sees per turn. The Redis cache between them keeps the per-turn resolve hot path off MariaDB.
Where it sits in the platform#
ScaiSkills is not a runtime. It does not execute anything, does not call models, does not hold conversation state. Other modules consume it:
- ScaiWave calls
/resolvebefore every channel turn to learn which skills should join the prompt, then calls the MCP tools as the LLM drills in. - ScaiCore calls
/resolveonce at agent boot withscope_type: coreand pins the result for the agent's lifetime. - ScaiMCP surfaces
skills.list,skills.search, andskills.viewas MCP tools to external agents. - ScaiMatrix holds the semantic index that powers
skills.search; ScaiSkills writes to it best-effort and reads from it on lookup.
If you only want one bot with a static system prompt, ScaiBot's tone configuration does the job. If you want shared instructions and references across multiple runtimes with explicit versioning, ScaiSkills is the place to put them.
What's in a bundle#
A skill bundle is a .tar.gz with one required file, SKILL.md, at the root. Its YAML frontmatter is the manifest — slug, semver, description, triggers, declared permissions, declared secrets, dependencies on other skills. The markdown body below the frontmatter is what the LLM reads when it calls skills.view on the slug. Optional reference documents go under references/ and are pullable on demand by path.
The bundle is stored content-addressed in S3 keyed by a SHA-256 of its bytes. Two skills with byte-identical bundles share storage; a single skill that publishes the same bytes twice gets a fresh version row pointing at the existing object. The version row carries the parsed manifest as JSON so resolution and search never need to reopen the tarball.
How a turn uses skills#
A typical ScaiWave channel turn touches ScaiSkills three times:
- Before the turn starts, the runtime calls
POST /resolvefor the channel scope. It receives the lightweight manifest list — slug, version, description, triggers — and feeds it into the LLM's system prompt via the preamble composer. - While generating, if the model recognises that a bound skill applies, it calls the
skills.viewMCP tool with the slug. The full body comes back; the model uses it to shape its response. - If the model is unsure which skill applies, it calls
skills.searchwith the user's intent. ScaiSkills runs a semantic search over the bound set and returns ranked matches — never out-of-scope skills.
ScaiCore agents do the same, except the resolve runs once at boot and the result is pinned for the agent's lifetime. The MCP surface behaves identically.
Where to go next#
- Quickstart — publish a skill, bind it, resolve it.
- Architecture — how publish, bind, resolve, and MCP fit together.
- Bindings and resolution — scope precedence, lockfiles, the pending-grants flag.
- API reference — every endpoint, request, response.
- Publish your first skill — full walkthrough of bundle layout and upload.
ScaiSkills' module ID inside ScaiGrid is scaiskills; its API is mounted at /v1/modules/scaiskills/.