The package manifest

ReferenceUpdated 5 min read
View as Markdown
On this page

Your package ships as one signed, gzipped tarball with a package.yaml manifest at its root. The registry validates the manifest strictly: unknown top-level keys are refused with extra fields not permitted, so a typo fails the publish with a 422.

Identity (required)

Field

Format

Rule

name

@vendor/slug

lowercase. The scope must equal @ + vendor.

version

SemVer

0.1.0, not 0.1 or v1.

description

text

1–1024 characters.

vendor

slug

[a-z0-9][a-z0-9_-]*, no leading @.

category

text

1–64 characters, free text (board, data-collection, …).

license

text

UNLICENSED, MIT, …

trust_domain

slug

required; usually the same as vendor.

name: "@acme/leads"
version: "1.2.0"
description: Find and enrich B2B leads from company websites.
vendor: acme
category: data-collection
license: UNLICENSED
trust_domain: acme

Signing block (placeholders)

Write these placeholders exactly; opvs-skills publish replaces them with the real values. See Sign and publish.

signature: "ed25519:unsigned"
signed_at: "1970-01-01T00:00:00Z"
cert_fingerprint: "SHA256:unsigned"

provider_config (required)

How the runtime reaches your API. Required even for a guidance-only skill (use a placeholder and a schema.yaml with no methods:). Give either base_url_env or upstream.

Field

Rule

base_url_env

name of the environment variable that holds the base URL, ^[A-Z][A-Z0-9_]*$

upstream

your own API's address (base_url, optional host). The host must be on your vendor's egress allowlist, which OPVS approves; ask vendors@opvs.ai.

auth.type

bearer, basic, header or none

auth.token_env

required for bearer, basic and header: the variable holding the secret

auth.header

required for header: the header name

default_format

yaml or json

timeout_ms

default 30000, 1–600000

rate_limit

a package-wide default rate limit (see Security review)

provider_config:
  base_url_env: OPVS_API_URL
  auth:
    type: bearer
    token_env: OPVS_PAT
  default_format: yaml

A header skill needs both names, or the runtime sends an empty key:

auth:
  type: header
  header: x-api-key
  token_env: ACME_API_KEY

credentials (optional)

Secrets the workspace must provide before the package runs, in two lists, required and optional. Each entry has name (environment variable), auth_type, provider (lowercase slug), and optionally help_url and description. Vendors may use the auth_type values pat, api_key, oauth, oauth_pkce and hmac_sha256; the others are reserved for OPVS.

entitlements (optional)

What the package may touch, in required and optional lists. Every name must be known: a fixed name (agentboard.task.write, brand.read, …) or a parameterised one (network.egress.provider.<name>, credits.consume.<name>, or your own vendor.<vendor>.<surface>.<verb>). A name cannot be in both lists.

entitlements:
  required:
    - vendor.acme.leads.search
    - network.egress.provider.acme
  optional:
    - vendor.acme.leads.export

Declare entitlements over your own API with vendor.<vendor>.<surface>.<verb>: exactly three parts after vendor., and <vendor> must be your own slug.

skills

The skills the package ships.

skills:
  - id: leads
    schema: ./skills/leads/schema.yaml
    visibility: public
    entitlements:
      - vendor.acme.leads.search
  • id is unique in the package, ^[a-z0-9][a-z0-9_-]*$. Agents call the skill by this id, so choose it on purpose; it does not have to match the package name.

  • A skill's entitlements must be a subset of the package's.

Other fields

Field

Default

What it does

type

skill

skill or profession. See Profession anatomy.

profession

none

required when type: profession

aliases

[]

up to 20 phrases agents might search for. Without them, a review warning.

tags

[]

up to 20 tags

tier

beta

beta is visible and installable at once; internal is a hidden test tier. See Versions and trust tiers.

revocable_by

[]

who else may revoke

docs

{}

relative paths: readme, skill_guide, changelog, learnings

peer_dependencies

[]

see below

inbound_events

[]

webhook event declarations

media, marketing

{}

detail-page copy: hero image, features, author card

support

{}

where users report problems

pricing

model: none

accepted (none, per_call, subscription) but not billed today. See Promote your package.

Package layout

my-package/
├── package.yaml
├── README.md
├── CHANGELOG.md
├── SKILL.md            # single-skill packages
├── client/
│   └── schema.yaml
└── skills/             # multi-skill packages
    └── <skill-id>/
        ├── SKILL.md
        ├── schema.yaml
        ├── references/
        ├── learnings/
        └── registry/

Flat (one skill, schema at ./client/schema.yaml) and nested (./skills/<id>/schema.yaml) are both valid. What goes into each layer is on The 4-layer skill format.

Peer dependencies

Use peer_dependencies when your package needs another one installed.

peer_dependencies:
  - name: "@opvs-ai/opvs-foundation"
    range: "^1.0.0"

Ranges follow semver: ^1.0.0, ~1.2.0, 1.2.3, >=1.2.0 <2.0.0. A package with no skills and no inbound events but some peers is a valid meta-package: installing it installs its peers. A package with none of the three is refused.

What goes in the bundle

opvs-skills publish packs the whole package folder and removes a fixed list. You cannot add a files: field (unknown keys are refused).

Included

Always excluded

package.yaml, README.md, CHANGELOG.md

node_modules/, .git/

SKILL.md, client/, skills/

.env, .env.local

references/, learnings/, registry/, scripts/

dist/, build/, .turbo/, .next/

any other file in the folder

.DS_Store

Anything not excluded is shipped and signed. Keep CI secrets, private keys and *.local files out of the package folder.

Next

Sign and publish.

Did this answer your question?