Skill Frontmatter Reference
On this page
This page is the field reference for a skill’s operator-facing metadata: required per-skill environment variables, required tools, and ancillary scripts. The skill’s body is the prompt content injected into the supervisor system prompt when the skill is loaded.
Read this as a field contract, not as a file format. The engine does not parse a
---block out of a skill’s body today:parseFrontmatter()exists inpackages/engine/src/utils/frontmatter.tsbut nothing in the runtime calls it. The fields below are supplied as structured values - through the admin panel’s skill form, through the create/update API, or inside a catalogue bundle - and the engine stores them itself. Writing them as YAML at the top of the body puts text in the prompt and sets nothing.
Where each field ends up: name, description and category are columns on the skills row; requiredEnv and requiredTools are written to the skill_versions.metadata jsonb column; scripts is its own skill_versions column.
Supported fields
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | yes | Display name. The slug is derived from it server-side - lowercased, with every character outside a-z0-9- replaced by -. There is no slug field to override it with, and the slug is immutable afterwards. Unique per organization. |
description | string | no | One-line summary shown in the catalog UI and in tool descriptions when the skill is auto-loaded. |
category | string | no | Free-form grouping for the catalog (e.g. operations, marketing). Defaults to general. Set on the skill itself, from the form or the create call - it is not per version. |
requiredEnv | array of strings or objects | no | Per-skill environment variables the operator must populate via PUT /api/instances/:slug/skills/:name/env. |
requiredTools | array of strings | no | Tool names exactly as registered: camelCase for a built-in tool (httpRequest), <namespace>:<tool> for a plugin tool (hubspot:contact, github:issue). They are auto-enabled on any agent that turns the skill on. A tool the organization cannot use is rejected on save, not warned about, and so is a tool’s old name from before it moved into a plugin (hubspotContact). |
scripts | array of script objects | no | Inline scripts shipped with the skill. Each entry: { file, description, content }. Catalogue-bundle only - the standard create and update calls do not accept it, so a skill authored through the form or the API carries no scripts. |
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: falseNormalised by normalizeRequiredEnv():
| Field | Type | Default | Notes |
|---|---|---|---|
name | string | - | Env var name. Always required. |
description | string | - | Optional help text shown in the admin UI under the input field. |
sensitive | boolean | true | When true, the value is masked in the UI, encrypted at rest and exposed by readSkill only as {{skill_env.<skill>.<KEY>}}. Set false only for configuration that may remain visible. |
Runtime handling
Values are scoped per agent and skill. For a sensitive entry, readSkill returns the opaque placeholder {{skill_env.<skill>.<KEY>}}; the runtime resolves it immediately before an eligible in-process tool executes, while the engine records the placeholder in tool and audit arguments. Non-sensitive entries may be returned inline. runSkillScript receives configured values only in the child process environment at execution time. A tool that returns a resolved value, or a script that prints one, can still expose it in its result.
scripts entry shape
| Field | Type | Notes |
|---|---|---|
file | string | Logical filename (used for display / extraction). |
description | string | One-line summary of what the script does. |
content | string | Full script body. No size limit beyond the text column maximum. |
Fields explicitly NOT supported
These are common mis-spellings or assumptions from other ecosystems. Nothing consumes them:
| Mistaken field | Use instead |
|---|---|
version | (none - versions are auto-incremented server-side on every PUT /api/organizations/:orgSlug/skills/:name) |
requiredSecrets | requiredEnv |
dependsOnTools | requiredTools |
language | (unused - set it in the body) |
tags | (unused - 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
Shown as YAML because it reads well as one block, and because a catalogue bundle carries the same field names. Remember that this is not a file you paste into the skill body: name, description and category go in the form’s own fields, requiredEnv and requiredTools in theirs, and scripts only through a bundle.
---
name: Issue Triage Workflow
description: Standard triage flow for incoming GitHub issues - label, route, escalate
category: operations
requiredEnv:
- TRIAGE_API_TOKEN
- name: TRIAGE_QUEUE_URL
description: Endpoint of the queue the tickets are read from
sensitive: false
- name: TRIAGE_SLACK_CHANNEL
description: Slack channel where escalations are announced (#ops-triage)
sensitive: false
requiredTools:
- httpRequest
- searchKnowledge
- 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 ticket comes in, follow these steps:
1. Fetch the ticket from the queue with `httpRequest`.
2. Classify it against the runbooks with `searchKnowledge`.
3. If the classification is `severity:high`, post to `#ops-triage` via `slackPostMessage`.
4. Reply with the runbook step if one matches.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.