CI publishing
Validate and publish contracts from CI with a platform API key.
The registry's flagship workflow is unispec validate / unispec publish
in CI, where interactive sign-in isn't possible. Registry endpoints accept
your platform API key (lb-sk_…) as a Bearer credential, so the same key
that authenticates the Memory/Vector/Knowledge/Agents APIs also publishes
contracts on behalf of your organization.
Setup
- Create an API key in the console (write scope).
- Add it to your repository secrets as
UNISPEC_API_KEY.
The CLI reads UNISPEC_API_KEY from the environment — no unispec login
needed in CI.
GitHub Actions
name: Publish contract
on:
push:
tags:
- "v*" # e.g. v1.2.0 — the contract version to publish
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Install the unispec CLI
run: npm install -g @unispec-ai/cli
- name: Validate
working-directory: contracts/support-triage
env:
UNISPEC_API_KEY: ${{ secrets.UNISPEC_API_KEY }}
run: unispec validate --create-if-missing
- name: Publish
working-directory: contracts/support-triage
env:
UNISPEC_API_KEY: ${{ secrets.UNISPEC_API_KEY }}
run: unispec publish --version "${GITHUB_REF_NAME#v}"Run unispec validate on every pull request (no tag filter) to catch contract
errors before they reach main; keep unispec publish behind a tag or release
so versions stay deliberate.
Useful flags for CI:
unispec publish --generate <target>— generate runtime artifacts (e.g.openai,unispec-agents) in the same step as the publish.unispec generate <owner>/<project>@<version> --download --output dist/— fetch generated artifacts as files for a later deploy step.unispec validate --owner <owner> --project <project>— override the coordinates from.unispec/project.json, e.g. to validate a fork against a staging project.
Reusable composite action
To reuse the validate/publish steps across repositories, drop this composite
action into .github/actions/unispec-publish/action.yml:
name: unispec-publish
description: Validate and publish a Unispec contract project
inputs:
working-directory:
description: Directory containing agent.yaml
required: true
version:
description: Contract version to publish (empty = validate only)
required: false
default: ""
api-key:
description: Unispec platform API key (lb-sk_…)
required: true
runs:
using: composite
steps:
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm install -g @unispec-ai/cli
shell: bash
- run: unispec validate --create-if-missing
shell: bash
working-directory: ${{ inputs.working-directory }}
env:
UNISPEC_API_KEY: ${{ inputs.api-key }}
- if: inputs.version != ''
run: unispec publish --version "${{ inputs.version }}"
shell: bash
working-directory: ${{ inputs.working-directory }}
env:
UNISPEC_API_KEY: ${{ inputs.api-key }}Then call it from any workflow:
- uses: ./.github/actions/unispec-publish
with:
working-directory: contracts/support-triage
version: ${{ github.ref_name }}
api-key: ${{ secrets.UNISPEC_API_KEY }}Validation badge
Every project serves an SVG badge with the validation status of its latest
published version at /projects/{owner}/{project}/badge.svg — public
projects serve it anonymously, so it embeds straight into a README:
[](https://unispec.ai/registry/acme/support-triage)States: validated (green) · warnings (amber) · failing (red) ·
unpublished (gray). Responses are cached for five minutes.
Environment variables
| Variable | Purpose |
|---|---|
UNISPEC_API_KEY | Platform API key — authenticates registry commands (and the product groups). |
UNISPEC_TOKEN | A user access token; takes precedence over the API key for registry commands. |
UNISPEC_BASE_URL | Override the registry base URL (defaults to https://registry.unispec.ai). |