Skip to main content
Skills

Skill Schemas

Forward API reference.

Skill object

Create, get, and list endpoints return this structure. content and content_encoding are included only when Get a Skill is called with include_content=true.
FieldTypeDescription
idstringSkill ID with the skill_ prefix
typestringAlways "skill"
display_titlestringDisplay title, which can be set independently of name in the Skill package. Duplicate values are allowed for the same user
sourcestringSkill source: custom or qoder
latest_versionstring | nullLatest version identifier with three states:
• After versioning, a Unix microsecond timestamp such as 1759178010641129;
• During migration before backfill, a legacy incremental counter such as 2;
• null after all versions are deleted.
It is not guaranteed to be incrementable with +1; clients must not use it to predict the next version
metadataobjectCustom metadata stored with the Skill; defaults to {} when omitted. created_by is reserved by Forward and must not be supplied by callers
created_atstringCreation time in RFC 3339 format
updated_atstringLast update time in RFC 3339 format
identity_idstring | nullOwning Forward identity. Returns the Identity ID when owned by an Identity; otherwise null. See Identity ownership
icon_urlstring | nullIcon URL associated by Forward
binding_infoBinding infoBinding information, such as Template reference counts
descriptionstringSkill description. ⚠️ Deprecated: New clients should read it from the version object; see Skill version object. Retained only for compatibility
contentstring⚠️ Deprecated: Base64-encoded zip content returned with include_content=true. Use the version-content download endpoint instead
content_encodingstring⚠️ Deprecated: Returned with content and always set to "base64". Use the version-content download endpoint instead

Identity ownership

An account (or Workspace) can have multiple Identities. Each Identity represents an end user of a product integrated with that account (or Workspace). A Skill can belong to an account (or Workspace) or to an Identity. A Skill Version always inherits ownership from its Skill and cannot have a separate owner. Ownership determines who can view and operate on the Skill and its versions.

Specifying ownership

CallerOwnershipHow to specify
PATAccount / WorkspaceOmit identity_id (the default, unchanged from previous behavior)
PATSpecified IdentitySupply the query parameter identity_id=<identity_id>
SAT (administrator)WorkspaceResolved automatically; cannot be switched with a parameter
SAT (bound to an Identity)That IdentityResolved automatically; cannot be switched with a parameter
identity_id is optional and is only used when operating on Identity-owned resources. A PAT can explicitly supply it; omitting it uses the administrator scope. For SATs, ownership is determined by the credential. To use Identity scope, issue an Identity-scoped credential and do not explicitly supply this parameter, even with an empty value. Any SAT, including Admin SAT, that supplies it receives HTTP 400. The Identity specified by a PAT must belong to the account or Workspace represented by that PAT and must be enabled. An Identity that does not exist, is disabled or deleted, or does not belong to the caller returns 404.

Ownership isolation

  • The administrator scope (a PAT without identity_id, or an Admin SAT) cannot see Identity-owned Skills.
  • An Identity cannot see Skills owned by the account (or Workspace) itself or by other Identities in the same account.
  • Within a valid Identity scope, cross-scope attempts to retrieve, download, update, or delete resources all return 404, without distinguishing between nonexistent resources and resources owned by someone else.
  • PATs without identity_id and Admin SATs retain the existing behavior: an owner mismatch returns 403. Downstream permission checks may also return 403.
  • Creation idempotency keys are isolated by ownership. Different Identities can reuse the same Idempotency-Key without replaying each other's requests.

Supported endpoints

Creating, searching, listing, retrieving, updating, and deleting Skills, as well as listing, creating, retrieving, downloading content from, and deleting Skill Versions, all support Identity scope.
GET /api/v1/forward/resources/batch does not support identity_id; its visibility rules remain unchanged.

Skill version object

List Skill Versions, Get a Skill Version, and Create a Skill Version return this structure. Retrieve version content with Download Skill Version Content, and soft-delete an existing version with Delete a Skill Version. A version is immutable after creation and is an independent snapshot of content and metadata.
FieldTypeDescription
idstringSkill Version ID with the skillver_ prefix
skill_idstringOwning Skill ID
versionstringVersion number. New versions return a 16-digit Unix microsecond timestamp; the three states of latest_version use the same value domain
namestringCanonical name parsed from name in the uploaded package's SKILL.md frontmatter
descriptionstringDescription parsed from description in the uploaded package's SKILL.md frontmatter
directorystringTop-level package directory name, equal to name
content_sizeintegerVersion package size in bytes, up to 50 MB
content_sha256stringSHA-256 digest of the version package content, in lowercase hexadecimal
statusstringVersion status; currently always active
created_atstringCreation time in RFC 3339 format
metadataobjectVersion-level metadata; currently always {}

Legacy version-number compatibility

The {version} path segment in GET /skills/{id}/versions/{version} accepts two forms:
  • Recommended: A 16-digit Unix microsecond timestamp such as 1759178010641129.
  • Compatibility: Legacy incremental counters such as "1" or "2" still resolve to the same version during migration. A nonexistent legacy number returns 404.
The literal latest is not supported and returns 400 invalid_request_error. Call Get a Skill, read latest_version, and use that value in the path. Both Download Skill Version Content and Get a Skill Version follow this rule.

Binding info

Reference summary included by Forward in Skill responses.
FieldTypeDescription
agent_template_countintegerNumber of Templates currently bound to the Skill

Skill package (upload rules)

Create a Skill and Create a Skill Version upload content with multipart/form-data. The recommended field is files. file is retained for compatibility (⚠️ deprecated; matching requests return Deprecation: true in the response headers). Migrate to files. Two upload forms are supported: ① Single .zip archive Upload one files part with Content-Type: application/zip. See "Package structure example" below. ② Bare file tree The files field can appear multiple times, with one file per part. Each part's filename carries a relative path, such as code-review/SKILL.md or code-review/scripts/run.sh. Forward normalizes parts independently of their order, packages them, and stores the result as a zip archive.
RuleDescription
Upload fieldfiles (repeatable parts); file (deprecated compatibility field for one zip archive)
Size limitBoth the compressed archive and its extracted contents must be no larger than 50 MB. Exceeding either limit returns 400 skill_content_too_large. Both the declared extracted size and actual extracted bytes are validated
Package manifestRequired SKILL.md under the top-level directory, with name and description in its frontmatter
Top-level directoryExactly one; its directory name must match name in SKILL.md

Package structure example

code-review/
├── SKILL              # Required; includes frontmatter name/description
├── scripts/
│   └── run.sh
└── data/
    └── rules.json

List pagination fields

Skill list responses use the same pagination fields as other Forward list endpoints.
FieldTypeDescription
dataarray of Skill objectsRecords on the current page
has_morebooleanWhether another page is available
next_pagestring | nullForward cursor for the next page (recommended). Equals the current page's last_id when has_more=true; otherwise null
first_idstring | nullID of the first record on the current page
last_idstring | nullID of the last record on the current page
The request cursor parameters page, after_id, and before_id are mutually exclusive; providing more than one returns 400. Use page where possible; it has the same semantics as after_id.

Skill version list pagination fields

Skill version list responses use only the recommended pagination fields.
FieldTypeDescription
dataarray of Skill version objectsRecords on the current page
has_morebooleanWhether another page is available
next_pagestringForward cursor for the next page; omitted when has_more=false
Best Practices
API reference