Preflight and common mistakes

How-toUpdated 4 min read
View as Markdown
On this page

Run these on your machine before every publish. The registry repeats the same checks, so a clean local run almost always means a clean publish.

1. opvs-skills generate   ← see the tools agents will get
2. opvs-skills validate   ← consistency check across the skill's files
3. opvs-skills publish --dry-run   ← the server's manifest rules + local signing, no upload
4. a real model call      ← the one check the others cannot replace

The CLI's built-in default folder is OPVS's own source layout, so always pass --skills-dir with the folder that holds your skills.

1. Generate

opvs-skills generate my-skill --skills-dir ./skills --dry-run

Read the output and check:

  • one typed tool per method in schema.yaml. A missing method usually means a YAML error;

  • tool names match your method names;

  • no name contains a dot, @, / or :. The rule is ^[a-zA-Z0-9_-]+$.

You never edit the generated output; you read it to confirm schema.yaml says what you meant.

2. Validate

opvs-skills validate my-skill --skills-dir ./skills

It checks that every method has a description, every parameter has a type, auth is well formed, the guidance block has the expected shape, tool names pass the regex, and the response contract holds. Fix every finding marked blocking; the registry would refuse the same thing.

Severity

Meaning

Action

blocking

the publish will be refused

fix it

warning

allowed, but it costs score and shows on the listing

fix it if cheap

info

for your information

none

3. Dry-run publish

opvs-skills publish ./my-package --dry-run --private-key @env:OPVS_SIGNING_KEY

This validates the manifest with the same strict rules the registry uses and signs the bundle locally, with no network call and no partner key. A green dry-run means the manifest is right and the bundle signs. The bundle-content checks of the security review still run on the server when you publish for real.

4. A real model call

A tool that "registered" is not proof that an agent can call it. Some model providers, OpenAI in particular, refuse the whole tool list if one name breaks the regex, so every agent that loaded your skill fails on its next turn.

Before you call a version done, drive a real conversation with an agent that has your skill loaded and check that:

  1. the model call returns (no HTTP 400 from the provider);

  2. your tools are in the tool list sent to the model;

  3. the model can call at least one of them by name.

The easiest way is an MCP client with your skill installed on a test workspace (see Use skills in your AI tool). OPVS can also run a sandbox test call or chat for you (opvs-skills test-call and opvs-skills chat); these use OPVS's admin sandbox today, so ask vendors@opvs.ai.

Common mistakes

Tool names with dots

The most important rule: every tool and method name matches ^[a-zA-Z0-9_-]+$. One dotted name breaks every agent that loads the skill, in every workspace. opvs-skills validate checks it; the real model call proves it.

requires.env that blocks loading

If your SKILL.md frontmatter declares metadata.openclaw.requires.env: [OPVS_API_URL, OPVS_PAT], the runtime checks those variables against your skill's own settings, not against what other skills provide. The skill then refuses to load even though the variables exist.

# wrong: blocks loading when another skill provides the variables
metadata:
  openclaw:
    requires:
      env: [OPVS_API_URL, OPVS_PAT]

# right: documentation only
metadata:
  openclaw:
    primaryEnv: OPVS_PAT

A header-auth skill without token_env

provider_config.auth.type: header needs both header: and token_env:. Without token_env the runtime sends an empty key. The registry now refuses this shape with a 422.

Declaring a method you do not serve

Every method in schema.yaml must have a real endpoint behind it, or each call to it fails even though the publish succeeded. If the skill teaches a method rather than calling an API, publish it guidance-only (no methods:).

Secrets next to package.yaml

The publish packs the whole package folder except a fixed exclude list (.env, .git, node_modules, build output). Anything else ships to every workspace. Keep keys and scratch files outside the folder. See what goes in the bundle.

Next

The package manifest.

Did this answer your question?