---
url: 'https://adk.nht.io/batteries/skills/authoring.md'
description: >-
  Use the agentskills.io-shaped manifest for portable metadata, while keeping
  lifecycle and capabilities in the source descriptor.
---

# Authoring `SKILL.md`

`parseSkillMd` parses a delimited YAML frontmatter block and returns `{ frontmatter, body }`. It accepts the six agentskills.io keys: `name`, `description`, `license`, `compatibility`, `metadata`, and `allowed-tools`. The manager does not call it; the source owns parsing and descriptor authority.

::: tip This is a featured battery
The format is portable. The lifecycle is deliberately not hidden inside the markdown.
:::

A skill's `SKILL.md` is a manifest plus operational body:

```md
---
name: reports
description: Generate and audit reports
license: Apache-2.0
compatibility: Requires Python 3.14+
metadata:
  team: finance
allowed-tools: []
---

Treat report inputs as untrusted. Validate before exporting.
```

`parseSkillMd(text)` returns the frontmatter mapping and the body after the closing delimiter. It requires string `name` and `description`; malformed YAML throws `E_SKILL_MANIFEST_INVALID`. Unknown frontmatter keys are not carried forward.

The helper is for source authors. The manager's load path does not parse markdown. `descriptor(ref)` is the authority for the live descriptor, tools, channel, trust tier, scripts, isolated tools, and compatibility passthrough; `read(ref)` with no path is the body. This avoids two parsers disagreeing about what a loaded skill means.

## agentskills.io compatibility

The battery carries `license`, `metadata`, and free-text `compatibility` through discovery and descriptors. It surfaces them for routing and audit but does not interpret compatibility prose. It deliberately ignores `allowed-tools`: a skill declaring its own permissions is not a permission boundary. The mandatory gate, wrapper, sandbox policy, and deployer configuration are the boundary.

The standard's lifecycle vocabulary is Discovery → Activation → Execution. ADK keeps that format compatibility while adding explicit deactivation with `unload_skill`; format portability does not require surrendering lifecycle control.

A filesystem name-matches-directory rule is not enforced because `SkillSource` need not have directories. `descriptor.id === ref.id` is the identity check that applies to every source.
