Skip to content

Workspace API

Workspace Skills

Personal and Workspace custom skills, immutable revisions, official installations, and the Skills API contract.

A skill is a portable instruction bundle a Spec run can load: a SKILL.md file plus optional inert reference files. This API is the public contract for discovery, reads, and lifecycle writes. The same routes serve the member web client, API-key clients, Spec, and the Developer MCP.

Personal and Workspace are audiences. Custom, official, and system are sources. They are not one enum. System skills stay hidden from public discovery; the reserved slugs create-skill and improve-skill cannot be claimed by a custom or official skill.

Audiences

AudienceWho sees itWho can edit
PersonalOnly the owning member. Invisible to API keys and to other members.The owner.
WorkspaceEvery member of the workspace, subject to lifecycle and object auth.The maintainer. Owners and admins may moderate, unpublish, delete, and transfer any Workspace skill. Creator attribution never changes.

Any active member may create, edit, and publish a Workspace skill they maintain.

Lifecycle and revisions

LifecycleMeaning
draftBeing written. Never discoverable. The Personal owner, or a Workspace maintainer, owner, or admin, may read it.
publishedThe current revision is live and discoverable. A Spec run may load it.
unpublishedWithdrawn from discovery. Revisions survive and it can be published again.
deletedTerminal. Discovery stops and no bundle is returned. A deleted Personal override does not hide a Workspace skill.

Published revisions are immutable. Update and publish send expectedDraftVersion. Unpublish, delete, transfer, and move send expectedVersion on the skill. Uninstall sends expectedVersion on the installation. Install has no expected version; it is ensure-state. A mismatch on a versioned write is 409 revision_conflict with the current version in allowlisted details.

list and get never return a deleted skill as a readable bundle. revisions lists published revisions only.

Run pins and official release resolution

Inside a Spec run, the first published read of a skill writes a run pin. Later published reads in that run return the same bytes even if a newer revision is published or an installation is re-pinned. The pin beats an explicit locator revisionId or releaseId and is applied silently; the returned detail names the revision served.

A pin bypasses two custom-get gates only: lifecycle !== 'published' and canReadPublished. A run that already held a pin can still read that revision after an unpublish. Soft delete and a skill-scope runtime block still refuse the next read. Official get has no post-pin lifecycle gate; uninstall mid-run does not block a pinned official read.

For an official skill the default release resolution order is:

  1. The run pin
  2. An explicit locator.releaseId
  3. The requesting actor’s installation release (Personal beats Workspace)
  4. Source latest

An official locator alone does not identify a bundle. Two members of one workspace can receive different bytes for the same official locator when one holds a personal installation at an older release. Production currently wires a not_populated official source: Explore is empty, and official get / install / official fork fail closed until a catalog is supplied.

Overrides

An override is a precedence mechanism, not a prohibition.

  • find applies it. A visible override suppresses its target in the same L1 result set, for every actor who can see the override, at any audience.
  • list returns both the override and its target so you can inspect or uninstall the overridden skill.
  • An explicit get of the overridden skill by locator is served.

The sanctioned shapes are Personal over Workspace-or-official, and Workspace over official. A Workspace skill cannot override a custom skill (400 invalid_input / override_audience). Draft, unpublished, deleted, and blocked overrides suppress nothing.

Runtime blocks

Prohibition is what skill-scope runtime blocks are for. A blocked custom or official skill disappears from find and list, and get / get-file fail closed with 403 disabled / runtime_block. Official fork and install apply the same key before content can be copied. uninstall is exempt so a block cannot strand an existing installation.

A skill_source block on custom or official degrades that source from L1 rather than raising.

Plan, scopes, and credits

Every Skills route requires the Pro plan for member and API-key principals. The gate runs after the workspace resolves and before the skill service. A non-Pro workspace receives 403 forbidden with the default Workspace API wording.

The verified Spec surface is exempt on the four allowlisted reads (find, list, get, get-file) so a free-plan Spec run can still load skills. revisions and every write, single and batch, stay Pro-gated for that same caller.

SurfaceAuthCredits
find, list, get, get-fileskills:read (API key or member JWT). Spec run tokens on the four reads.0
revisionsskills:read0
Create, update, publish, unpublish, delete, transfer, move, fork, install, uninstall (and each /batch)skills:write0

Reads fail closed when skill loading is off (state: 'disabled' on find / list). Writes fail closed when skill writes are off.

Idempotency and receipts

Every write carries an idempotency key. Single routes require the Idempotency-Key header (1-200 characters). Each batch item carries idempotencyKey. MCP tools expose the same field. The store keeps a request digest and a bounded metadata receipt, never a second copy of skill content.

Every write returns a content-free receipt:

SkillWriteReceipt
{
"skillId": "8a1f3c2e-0001-4b7d-9e5a-000000000010",
"installationId": null,
"draftVersion": 1,
"publishedRevisionId": null,
"lifecycle": "draft",
"changed": true
}

Errors

Skills errors use a dedicated map. They are not the Data API errors page.

Error envelope
{
"error": {
"code": "revision_conflict",
"message": "skill revision_conflict",
"reason": "stale_draft_version",
"details": { "currentDraftVersion": 4 }
}
}
Service codeHTTP
invalid_input400
validation, limit_exceeded422
not_found, official_source_not_populated404
forbidden, disabled403
revision_conflict, idempotency_conflict, slug_conflict, lifecycle_conflict409
official_source_unavailable503
internal_error500

details is optional and allowlisted to exactly these keys: path, currentVersion, currentDraftVersion, baseRevisionId, rootSha256, bundleSha256. Batch per-item errors carry the same four fields (code, message, reason, details). Envelope problems (empty batch, more than 100 items, malformed body) stay request-validation 400.