Problem
Today the SDK can only load Agent Skills from the local filesystem (skill_directories / skillDirectories). Applications whose skills live somewhere else have to write every SKILL.md to disk before the session starts. Examples of "somewhere else":
- remote MCP servers that implement the MCP Skills extension
- a database
- a per-user or per-tenant store
- a content service
Writing the files to disk up front causes several problems:
- Everything is fetched eagerly. Skills are designed for progressive disclosure: the model sees only names and descriptions until it activates a skill. Writing files to disk means downloading every skill's full content at session start, including skills that are never used.
- Content goes stale. Files written at startup can't reflect a source that changes during a long-lived session, and invalidating or refreshing them means rewriting the filesystem.
- Content can't be verified at activation. An application that wants to check content when the skill actually loads, for example against an expected digest or size, has no hook. Once a file is on disk, it can change between listing and activation.
- Sessions aren't isolated. Multi-session hosts must create and clean up a separate directory tree per session to keep one session's skills out of another's.
- The host needs extra write access. Environments with read-only or restricted filesystems must grant write access just to stage skills.
- The source is invisible. Skills from different sources are indistinguishable once copied to disk, so name collisions and provenance are hard to handle.
Proposed solution
Add a public, session-scoped skill provider option to session configuration in every SDK language. The host supplies callbacks instead of files:
class SkillProvider(Protocol):
async def list_skills(self) -> list[SkillDescriptor]:
"""Return metadata only (name, description, optional frontmatter). No content."""
async def read_skill(self, name: str) -> str | bytes:
"""Return the full SKILL.md. Called lazily, only when the skill is activated."""
session = await client.create_session(
SessionConfig(skill_provider=MyProvider(), ...)
)
(TypeScript and .NET would expose the equivalent skillProvider option.)
Requested semantics
- Lazy content.
list returns metadata only; read is called only when the model or user activates that skill.
- Session scope. A provider is bound to one session and is never shared with or visible to another session.
- Async and cancellable. Both callbacks are async, honor cancellation, and run under a documented timeout.
- Failure stays local. A
list or read error makes the affected skill (or catalog) unavailable and surfaces a typed error or event. It does not fail the session or turn.
- Works alongside
skill_directories. The provider and directories can be used together, with documented precedence or name-collision rules.
- Lifecycle. The provider is released when the session closes or disconnects. Resuming a session either re-binds a provider or documents that the host must supply one again.
- Documented limits. Maximum catalog size, description length and
SKILL.md size are documented so hosts can enforce the same bounds.
- Capability detection. Hosts can detect whether the connected CLI/runtime supports providers (for example a capability flag or version check), so they can fall back to
skill_directories on older runtimes.
- Optional provenance. A descriptor can carry an origin label, so the UI and model can tell skills from different sources apart.
Why this belongs in the SDK
The CLI's JSON-RPC surface appears to already have provider-style skill callbacks (list/read). The main gap seems to be a stable, documented, public SDK API over that surface. Without one, consumers either write files to disk (with the problems above) or depend on unpublished protocol details that can break between releases.
Relevance to the MCP Skills extension
The MCP Skills extension (io.modelcontextprotocol/skills, SEP-2640, Final) standardizes how MCP servers serve Agent Skills. Its model matches the provider proposed here, which makes a provider API the natural way for SDK hosts to support MCP-served skills without writing files to disk:
| MCP Skills extension |
Skill provider |
skills/list returns metadata only: complete frontmatter plus a file manifest with SHA-256 digest and size, and no content |
list_skills() returns descriptors only |
Content is read separately with resources/read, and reading does not itself activate a skill |
read_skill() is called lazily, only on activation |
| "The host routes the read through its skill-loading path, which verifies the content and applies any required user approval before loading it into model context" |
The read callback is the host's hook to check digest and size and apply approval before content reaches the model. Writing files to disk up front removes that hook. |
| Skill identity is the originating server identity plus the URI. Names are labels, not unique, and hosts must preserve server identity |
Descriptors need a stable identity or origin plus collision rules (semantics 5 and 9) |
List results carry ttlMs and cacheScope |
Hosts need a way to refresh the catalog during a session (semantic 10) |
SKILL.md may reference supporting files resolved against the skill's root directory |
The provider needs to serve supporting files, not only SKILL.md (semantic 11) |
The extension notes that SDK and host support is still being implemented (see the client support matrix). A public provider API would let any Copilot SDK host bridge an MCP Skills server to a session with a thin adapter that maps skills/list to list and resources/read to read, and would make the SDK a natural entry in that matrix.
Additional semantics implied by the extension
- Catalog refresh. A host can tell the session that its catalog changed (or the runtime re-calls
list after a host-supplied TTL), so updated or withdrawn skills don't stay visible for the rest of a long session.
- Supporting files.
read can fetch files relative to a skill's root (for example read_skill_file(name, "references/checklist.md")), so multi-file skills work without writing anything to disk.
Acceptance criteria
Related
Problem
Today the SDK can only load Agent Skills from the local filesystem (
skill_directories/skillDirectories). Applications whose skills live somewhere else have to write everySKILL.mdto disk before the session starts. Examples of "somewhere else":Writing the files to disk up front causes several problems:
Proposed solution
Add a public, session-scoped skill provider option to session configuration in every SDK language. The host supplies callbacks instead of files:
(TypeScript and .NET would expose the equivalent
skillProvideroption.)Requested semantics
listreturns metadata only;readis called only when the model or user activates that skill.listorreaderror makes the affected skill (or catalog) unavailable and surfaces a typed error or event. It does not fail the session or turn.skill_directories. The provider and directories can be used together, with documented precedence or name-collision rules.SKILL.mdsize are documented so hosts can enforce the same bounds.skill_directorieson older runtimes.Why this belongs in the SDK
The CLI's JSON-RPC surface appears to already have provider-style skill callbacks (
list/read). The main gap seems to be a stable, documented, public SDK API over that surface. Without one, consumers either write files to disk (with the problems above) or depend on unpublished protocol details that can break between releases.Relevance to the MCP Skills extension
The MCP Skills extension (
io.modelcontextprotocol/skills, SEP-2640, Final) standardizes how MCP servers serve Agent Skills. Its model matches the provider proposed here, which makes a provider API the natural way for SDK hosts to support MCP-served skills without writing files to disk:skills/listreturns metadata only: complete frontmatter plus a file manifest with SHA-256 digest and size, and no contentlist_skills()returns descriptors onlyresources/read, and reading does not itself activate a skillread_skill()is called lazily, only on activationttlMsandcacheScopeSKILL.mdmay reference supporting files resolved against the skill's root directorySKILL.md(semantic 11)The extension notes that SDK and host support is still being implemented (see the client support matrix). A public provider API would let any Copilot SDK host bridge an MCP Skills server to a session with a thin adapter that maps
skills/listto list andresources/readto read, and would make the SDK a natural entry in that matrix.Additional semantics implied by the extension
listafter a host-supplied TTL), so updated or withdrawn skills don't stay visible for the rest of a long session.readcan fetch files relative to a skill's root (for exampleread_skill_file(name, "references/checklist.md")), so multi-file skills work without writing anything to disk.Acceptance criteria
skill_provider/skillProvidersession option in the Python, TypeScript and .NET SDKsreadverified: no content is requested during listingRelated