Skip to Content
Polyant is open source under AGPL-3.0 — star us on GitHub.
ReferenceSkill Frontmatter

Skill Frontmatter Reference

Skills are markdown documents with optional YAML frontmatter. The frontmatter declares operator-facing metadata: required per-skill environment variables, required tools, and ancillary scripts. The body of the document (everything after the closing ---) is the prompt content injected into the supervisor system prompt when the skill is loaded.

Frontmatter is parsed by parseFrontmatter() in packages/engine/src/utils/frontmatter.ts. The parser is intentionally minimal (no full YAML support) — it handles key: value, string lists, and one level of nested object lists. The resulting metadata is stored on the skill_versions.metadata jsonb column (packages/engine/src/skills/schema.ts:29) and the requiredEnv / requiredTools projections are surfaced by skills.service.ts.

Supported fields

FieldTypeRequiredNotes
namestringnoDisplay name. The slug is derived server-side via slugify(name) — overridden by slug if explicitly set.
descriptionstringnoOne-line summary shown in the catalog UI and in tool descriptions when the skill is auto-loaded.
categorystringnoFree-form grouping for the catalog (e.g. operations, marketing). Defaults to general.
requiredEnvarray of strings or objectsnoPer-skill environment variables the operator must populate via PUT /api/instances/:slug/skills/:name/env.
requiredToolsarray of stringsnoTool names (camelCase, exactly as registered) that must be enabled on the instance for the skill to work.
scriptsarray of script objectsnoInline scripts shipped with the skill. Each entry: { file, description, content }. Stored as jsonb.

requiredEnv entry shape

Two forms are accepted, mixed in the same array:

requiredEnv: - GITHUB_TOKEN # shorthand (string) — sensitive=true assumed - name: GITHUB_OWNER # full form description: GitHub owner / org used in API calls sensitive: false

Normalised by normalizeRequiredEnv():

FieldTypeDefaultNotes
namestringEnv var name. Always required.
descriptionstringOptional help text shown in the admin UI under the input field.
sensitivebooleantrueWhen true the value is masked in the UI and encrypted at rest. Set to false for non-secret config (e.g. an owner name).

scripts entry shape

FieldTypeNotes
filestringLogical filename (used for display / extraction).
descriptionstringOne-line summary of what the script does.
contentstringFull script body. No size limit beyond the text column maximum.

Fields explicitly NOT supported

These are common mis-spellings or assumptions from other ecosystems — the parser ignores them:

Mistaken fieldUse instead
version(none — versions are auto-incremented server-side on every PUT /api/skills/:name)
requiredSecretsrequiredEnv
dependsOnToolsrequiredTools
language(not parsed — set it in the body)
tags(not parsed — use category)
author(not parsed)

The parser stores any unknown keys it sees in the raw metadata jsonb but they are never surfaced through the API or UI — treat them as dropped.

Full example

--- name: Issue Triage Workflow description: Standard triage flow for incoming GitHub issues — label, route, escalate category: operations requiredEnv: - GITHUB_TOKEN - name: GITHUB_OWNER description: GitHub owner or organisation sensitive: false - name: TRIAGE_SLACK_CHANNEL description: Slack channel where escalations are announced (#ops-triage) sensitive: false requiredTools: - ghIssue - ghPR - slackPostMessage scripts: - file: extract-metadata.py description: Pull issue title / labels / reporter into a structured record content: | import sys, json data = json.loads(sys.stdin.read()) print(json.dumps({"title": data["title"], "labels": [l["name"] for l in data["labels"]]})) --- # Issue Triage When a new GitHub issue comes in, follow these steps: 1. Read the issue with `ghIssue`. 2. Apply labels based on the title prefix. 3. If the label is `severity:high`, post to `#ops-triage` via `slackPostMessage`. 4. Open a draft PR with `ghPR` if a fix is obvious.

The body (everything after the closing ---) is the prompt content that gets injected into the supervisor when the skill is loaded — either auto-loaded via the auto-load flag, or surfaced through readSkill.

Last updated on