Skills (kind: "skill")
Status: Normative. Extends the package model with a seventh kind — a skill bundle: one or more Agent Skills an AI-agent host loads. The SDK Kind/manifest wiring, the @azphalt/azp verification rules (validateSkillManifest folded into verifyAzp), the create-azphalt template, the registry discovery profile, and the skill host-conformance profile (runSkillConformance) are all implemented and on main. Modeled on how this spec already treats an MCP server (mcp-server.md): the package declares the bundled skill(s); the host's own agent runtime reads and exposes them.
Why this exists — and why it doesn't break the moat
A skill is instructional text (a SKILL.md, plus optional scripts/, references/, assets/) an AI agent reads to learn how to do something — it is not code an azphalt runtime executes, and it touches none of the editor surface a code extension can reach (see capability-model.md). So, like an MCP server, a skill bundle cannot be an azphalt-sandboxed code extension, and this spec does not try to make it one.
Instead it reuses the header pattern proven for MCP servers and companion apps: the uploaded .azp carries no /code sandbox payload and declares no capabilities. Unlike those two kinds it does bundle a real payload — the SKILL.md files and their support directories — because that payload is the skill; there is nothing to "connect to" or "launch" the way there is for a server or a companion app. The moat holds because:
- azphalt grants a skill package no editor capability. It reaches nothing of the host's editor surface (layers, bitmaps, canvas). The never-list is unaffected.
- The
.azpcarries nocapabilities, noentry/runtime. A skill host's agent loop readsSKILL.mdas text and decides what to do with it under whatever sandboxing that host already applies to its own agent — azphalt's part ends at distributing a signed, verifiable bundle. - The
SKILL.mdformat itself — frontmatter fields, thescripts//references//assets/convention, how a host is meant to select and load a skill — is defined by the external Agent Skills specification, the same waymcp-server.mddefers wire-protocol semantics to the Model Context Protocol. This spec defines only how a skill bundle is packaged and discovered inside a.azp.
The result: the marketplace grows from assets + sandboxed filters + companion apps + MCP servers to also carry skills — users upload them the way they publish any other package — without widening what a sandboxed extension can do.
The package (kind: "skill")
A normal signed .azp whose kind is "skill". It carries no capabilities and no entry — it is a bundle of one or more skills. Its manifest adds one block, skill:
{
"azphalt": "0.1",
"id": "com.acme.azphalt.release-notes-skill",
"name": "Release Notes",
"version": "1.0.0",
"kind": "skill",
"license": "MIT",
"compat": ">=0.1",
"skill": {
"skills": [
{
"id": "release-notes",
"name": "Release Notes",
"description": "Draft release notes from a range of commits."
}
]
},
"files": {
"skills/release-notes/SKILL.md": "sha256-…",
"skills/release-notes/scripts/collect-commits.sh": "sha256-…",
"skills/release-notes/references/style-guide.md": "sha256-…"
}
}skill block fields
skills[]— one or more bundled skills (at least one required). Each entry has:id— a directory-safe name; the package payload has the skill atskills/<id>/SKILL.md.name/description(optional) — mirror theSKILL.mdfrontmatter. Advisory: they power the store card and a host's browse list without extracting and parsing every bundled skill; a host that readsSKILL.mdtreats it, not this block, as authoritative.
Discovery & layout
Each entry in skill.skills corresponds to a directory skills/<id>/ in the package payload, containing at minimum a SKILL.md file — the same discovery convention the Agent Plugins Specification defines for a plugin's skills/ directory: one level of subdirectories, each identified by a SKILL.md at its top, with no recursive search for additional skills beneath it. scripts/, references/, and assets/ are conventional subdirectories a SKILL.md may point into, per the Agent Skills format; azphalt does not interpret their contents.
A skill's SKILL.md MUST resolve within the filesystem-resolved plugin root (package-format.md § path containment applies to every payload path, not only skills). Whether a discovered SKILL.md itself conforms to the Agent Skills format — required frontmatter fields, body structure — is validated by the host's skill loader, not by azphalt package verification; a host that finds a bundled SKILL.md it cannot parse skips that skill and continues loading the rest of the package, the same tolerance mcp-server.md gives an unrecognized offers shape.
Verification
verifyAzp applies these rules to a kind: "skill" manifest (in addition to the container integrity and signature checks every package gets). Reference: @azphalt/azp's validateSkillManifest.
- The manifest has a
skillblock, and is header-only: noentry/runtime, nocapabilities, noassets, noapp/mcp/packblock. skill.skillshas ≥ 1 entry; every entry has a non-empty, directory-safeid(no path separators, not.or..), unique within the package.- Every entry's
skills/<id>/SKILL.mdnames a path present inmanifest.files— a declared skill MUST be a real, integrity-covered payload entry, not just a claim in the manifest.
Verification does not parse SKILL.md itself or validate it against the Agent Skills frontmatter schema — that is a host-side concern, exactly as mcp-server.md's offers block is advisory and the live MCP handshake is authoritative.
Signing (verifyTrust), registry counter-signing, and the /revocations feed apply unchanged (package-format.md § Signing, repository-api.md § Revocations).
Discovery & registry
A skill package lists in the registry like any other package:
kind: "skill"flows through the browse/search summary (repository-api.md— each summary carrieskind) and the package detail (GET /packages/{id}→manifest.skill), so a host tells it apart without a per-package round-trip.- A registry that carries skill packages advertises the
"skill"conformance profile in/.well-known/azphalt-repository.jsonprofiles(repository-api.md § Supported types and profiles), so only a host that implements an agent skill loader browses for them. - App-scoping (
targetApps) works as-is: a skill meant for one host's agent is app-scoped; a general one omitstargetAppsand is global.
Publishing is the existing path — the registry verifies (the rules above) and indexes the package; no new distribution endpoint is introduced.
Conformance
@azphalt/conformance ships a skill host-conformance profile, runSkillConformance(host) (mirroring the mcp profile): it drives a fixture kind:"skill" package and asserts the host verifies the header, refuses a tampered / unsafe-path / non-kind:"skill" / incompatible package, and surfaces the bundled skill's id. A conforming host declares a "skill" profile for registry matching.