Skill Development Guide
Version française : ../../fr/guides/skill-development.md
This guide shows how to write, sign, publish, load, version and retire a skill. It is for developers with the
developer or tenant_admin role; changing the status of a skill needs tenant_admin or security_officer.
Concept
A skill is a set of instructions (its SKILL.md) and an optional entrypoint that an agent loads at run time. The Skill
Registry stores the manifest, the content and its SHA-256 digest; the Skill Loader hands the skill to an agent only
when the digest matches, the signature is verified, the agent lists the skill in spec.skills and the agent was
granted every scope of the skill. A skill is data for the model: it never replaces a permission check.
The statuses are draft, approved, restricted, deprecated and blocked. A verified skill becomes approved at
registration; an unverified one stays draft.
Manifest fields
The manifest follows contracts/v1/skill-manifest.schema.json.
| Field | Type | Required | Description |
|---|---|---|---|
apiVersion, kind | string | yes | enterprise-ai.io/v1 and Skill. |
metadata.name, metadata.version, metadata.owner | string | yes | DNS like name, semver version, accountable owner. |
spec.description | string | yes | When the agent should use the skill. |
spec.instructions | string | yes | The SKILL.md content stored inline. |
spec.entrypoint | string | no | Code entrypoint when the skill ships code. |
spec.dependencies | array | no | Each item: ref, version, optional. |
spec.permissions | object | yes | data_classification_max (required), scopes, network (boolean), filesystem (none, read, write). |
spec.artifact | object | no | oci_ref or git_ref, and digest (sha256:<64 hex>), required for a Git or OCI artifact. |
spec.signature | object | no | digest (required), cosign_bundle, signer, issued_at. |
spec.compatible_runtimes | array | no | Runtimes the skill was tested with. |
Create a skill
A skill is described by a skill.yaml manifest (contracts/v1/skill-manifest.schema.json) and its SKILL.md; enterprise-ai create skill writes them and validates the manifest.
enterprise-ai create skill invoice-reader
enterprise-ai validate -f invoice-reader/skill.yaml
Steps
-
Create the skill. The command writes
skill.yamlandSKILL.md, then validates the manifest against the v1 contract. In the portal: Developer Studio > Skill studio > New.enterprise-ai create skill invoice-readerExpected result: the two files are listed and the manifest is marked valid against
skill-manifest.If it fails: exit code 1 with "exists" means the files are already there; add
--forceor pick another name. -
Write the instructions and the permissions. Describe in SKILL.md when to use the skill, its steps and the tools it relies on. Set
spec.permissions.scopesanddata_classification_maxto what the skill really needs: the loader refuses it to an agent that was not granted these scopes.Expected result: SKILL.md and
spec.instructionssay the same thing.If it fails: an agent whose
data_classification_maxis above the one of the skill gets 403skill_permission_deniedat load time. -
Validate the manifest. Offline check against the contract. In the portal: Validate on the server.
enterprise-ai validate -f invoice-reader/skill.yamlExpected result: exit code 0.
If it fails: exit code 1 lists the invalid fields.
-
Compute the digest and sign.
publish skillcomputes the SHA-256 digest of the folder, writes it inspec.artifact.digestandspec.signature.digest, and with--signsigns withcosign sign-blob. Run it first with--dry-runto see the manifest that will be sent.enterprise-ai publish skill ./invoice-reader --sign --key cosign.key --dry-runcosign.key: your cosign key file or a KMS reference.Expected result: the digest
sha256:...is printed, then the manifest in YAML.If it fails: a warning says that
cosignis missing; install it or publish unsigned (the skill will staydraftand cannot be loaded). -
Publish. Without
--dry-runthe command calls POST /v1/skills. In the portal: Save as a new version.enterprise-ai publish skill ./invoice-reader --sign --key cosign.keyExpected result:
apply_statusiscreatedorupdated, andverifiedistrue.If it fails: 422
invalid_manifestwithartifact.digestmeans a Git or OCI artifact without its digest. -
Verify the signature. POST /v1/skills/{name}/verify checks the digest and the signature of the stored version again. In the portal: Skill studio > skill > Test > Verify.
Expected result:
verified: true, withmethodandsigner.If it fails:
reasonisdigest_mismatch(content changed after signing) or the signature is missing. -
Grant the skill to an agent and load it. Add
skill:invoice-reader@<version>tospec.skillsof the agent, apply the agent, then the runtime calls GET /v1/skills/{name}/load with?agent=<agent>.Expected result: the answer gives
digest,signer,instructions,permissionsanddependencies.If it fails: see the troubleshooting table; each refusal is audited as
skill.loadwith its reason. -
Publish a new version. Raise
metadata.version, sign and publish again. The stored version is replaced, its verification is run again, and ablockedskill staysblocked.Expected result:
apply_statusisupdated.If it fails: run step 6 again and read
reason. -
Restrict, deprecate or block. POST /v1/skills/{name}/status applies
draft,restricted,deprecatedorblockedat once;approvedopens a promotion approval and answers 202, decided with POST /v1/approvals/{approval_id}/decide (Agents > Approvals inbox).client.skills.set_status("invoice-reader", "blocked", reason="prompt injection found")Expected result: the new status is returned; a
blockedordeprecatedskill is no longer loaded.If it fails: 400
invalid_requestfor an unknown status.
Sign and publish
enterprise-ai publish skill checks the signature (cosign sign-blob with --sign) then calls POST /v1/skills; POST /v1/skills/{name}/verify checks the signature again and GET /v1/skills/{name}/load loads the verified skill.
enterprise-ai publish skill ./invoice-reader --sign --key cosign.key --dry-run
Verify from code
An unsigned skill or one whose signature does not match is never loaded.
client.skills.verify("invoice-reader")
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
404 skill_not_found | No skill with this name in the tenant. | Check the name with enterprise-ai get skills. |
422 invalid_manifest | Contract error, or a Git or OCI artifact without artifact.digest. | Validate the manifest; publish with enterprise-ai publish skill, which sets the digest. |
403 skill_blocked | The skill is blocked or deprecated. | Publish a fixed version and ask a tenant_admin to change the status. |
409 skill_digest_mismatch | The stored content no longer matches its digest. | Sign and publish the content again. |
403 skill_unsigned | The signature is missing or not verified. | Publish with --sign and a trusted key. |
403 skill_not_granted | The agent does not list the skill in spec.skills. | Add the reference to the agent manifest and apply it. |
403 skill_permission_denied | The skill needs a scope the agent lacks, or the agent classification is above the skill one. | Align spec.permissions of the skill and of the agent. |
400 invalid_request | Unknown status in POST /v1/skills/{name}/status. | Use draft, approved, restricted, deprecated or blocked. |
Next steps
- Agent development guide to grant the skill.
- Pack development guide to ship skills inside a Marketplace pack.
- Testing guide and CLI reference.