# Preflight and common mistakes

Source: https://opvs.ai/docs/guides/vendors/preflight

> Check a package on your own machine before you publish, and avoid the mistakes that catch first-time authors.

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

```bash
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

```bash
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](https://opvs.ai/docs/guides/vendors/skill-anatomy.md#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

```bash
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](https://opvs.ai/docs/guides/vendors/security-review.md) 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](https://opvs.ai/docs/guides/use-skills-in-your-ai-tool.md)). 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.

```yaml
# 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](https://opvs.ai/docs/guides/vendors/package-manifest.md#what-goes-in-the-bundle).

## Next

[The package manifest](https://opvs.ai/docs/guides/vendors/package-manifest.md).
