> ## Documentation Index
> Fetch the complete documentation index at: https://amd-gaia.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Skill Format

> SKILL.md field grammar — Agent Skills (agentskills.io) base + a metadata.gaia namespace, permission model, security tiers, and Hermes/OpenClaw compatibility

<Info>
  **Grounds on (exists today):** [`src/gaia/agents/base/tools.py`](https://github.com/amd/gaia/blob/main/src/gaia/agents/base/tools.py) (`@tool`, `_TOOL_REGISTRY`) · [`src/gaia/agents/registry.py`](https://github.com/amd/gaia/blob/main/src/gaia/agents/registry.py) (`KNOWN_TOOLS`, `namespaced_agent_id`) · [`src/gaia/connectors/providers/base.py`](https://github.com/amd/gaia/blob/main/src/gaia/connectors/providers/base.py) (`ConnectorRequirement`) · [`src/gaia/ui/routers/agents.py`](https://github.com/amd/gaia/blob/main/src/gaia/ui/routers/agents.py) (`/api/agents`, the panel to mirror)

  **Proposed runtime (not written yet):** the `gaia.skills` loader, the `gaia skill` CLI, and the `/api/skills` router. Every such symbol is marked **PROPOSED** where it appears.
</Info>

<Note>
  **Component:** the `SKILL.md` field grammar — the on-disk contract for GAIA's skill ecosystem (issue [#691](https://github.com/amd/gaia/issues/691)).

  **Module:** `gaia.skills` — **PROPOSED, greenfield.** No loader, CLI, or registry code exists. The contract is grounded on the live tool registry in `gaia.agents.base.tools`.

  **Status:** **Format = decided** (this revision). **Runtime = proposed.** The companion [Agent Skills](/docs/spec/agent-skills) spec owns the *integration surface* (discovery, scoping, progressive disclosure); this document is authoritative for the *field grammar*.

  **Target consumers:** [#887](https://github.com/amd/gaia/issues/887) (skill auto-synthesis), [#553](https://github.com/amd/gaia/issues/553) (self-improving agent), [#1451](https://github.com/amd/gaia/issues/1451) (tool-loader Part 3), [#647](https://github.com/amd/gaia/issues/647) (skill marketplace), [#648](https://github.com/amd/gaia/issues/648) (OEM bundling), [#462](https://github.com/amd/gaia/issues/462) (Agent Manifest).
</Note>

***

## Why this exists

A GAIA agent's capabilities are compiled in. Tools arrive through hardcoded
mixins (`RAGToolsMixin`, `BrowserToolsMixin`, … catalogued in `KNOWN_TOOLS`,
[`registry.py:38`](https://github.com/amd/gaia/blob/main/src/gaia/agents/registry.py))
wired into the agent class and shipped inside the wheel. A user who wants a new
capability has no path short of forking the agent. **Skills** make a capability
portable: a folder with a `SKILL.md` an agent loads only when relevant.

The [Agent Skills](/docs/spec/agent-skills) spec answers *why skills, and how an agent
composes them*. This document answers a narrower, higher-stakes question: **what
exactly goes in the frontmatter.** That matters because the frontmatter is a
*contract*, not a private detail — several landed and in-flight features read or
emit these fields:

* **[#887](https://github.com/amd/gaia/issues/887)** (skill auto-synthesis) and
  **[#553](https://github.com/amd/gaia/issues/553)** (self-improving agent) will
  *emit* `SKILL.md` files via skill extraction. The field names they write must be
  the field names this spec defines.
* **[#1451](https://github.com/amd/gaia/issues/1451)** (tool-loader Part 3)
  *reads* the `tools_required` field to union a recipe's tools into per-turn tool
  selection — a hard cross-spec dependency already written down in
  [`tool-loader.mdx`](/docs/plans/tool-loader#part-3-skill-driven-signal-gated-on-887).
* **[#647](https://github.com/amd/gaia/issues/647)** (marketplace) and
  **[#648](https://github.com/amd/gaia/issues/648)** (OEM bundling) need a stable
  definition of "a skill" and its trust tiers to publish and pre-bundle.

So the single thing this spec must nail down is a frontmatter schema that is
**(a)** the open standard, so the existing skill ecosystem works in GAIA
unchanged; **(b)** a strict superset that carries GAIA's typed tools,
permissions, and trust tiers; and **(c)** stable enough that the consumers above
can build against it without churn.

### Prior art (credit before contribution)

GAIA does **not** invent a skill format. It adopts one and extends the
frontmatter. The base and the compatible formats:

| Source                                                           | What it contributes                                                                                                                                                                                                                                                            |
| ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **[Agent Skills](https://agentskills.io)** (used by Claude Code) | The base standard GAIA adopts: required `name` + `description`, optional `license` + `metadata` (an arbitrary map; "make key names reasonably unique"), a folder of `SKILL.md` + `scripts/`/`references/`/`assets/`, and progressive disclosure (metadata → body → resources). |
| **Hermes Agent** (Nous Research)                                 | The `metadata.hermes` namespace pattern — vendor-specific fields nested under `metadata.<vendor>` so standard runtimes ignore them losslessly.                                                                                                                                 |
| **OpenClaw / ClawHub**                                           | The same `metadata.openclaw` namespace pattern, confirmed by the format owner.                                                                                                                                                                                                 |
| **Claude Code skills**                                           | The reference implementation of the Agent Skills standard; already credited in [Agent Skills](/docs/spec/agent-skills).                                                                                                                                                             |

**GAIA's contribution** is the `metadata.gaia` namespace: typed `@tool`
declarations, a `<domain>:<level>` permission grammar bridged to the connector
grant model, three install-time security tiers, and the `tools_required` recipe
contract — all expressed *inside* the standard's `metadata` map, so a GAIA skill
remains a valid standard skill.

***

## Decided design

The schema is the standard's required base plus a single GAIA-owned namespace.
A standard runtime reads the base and ignores `metadata.gaia`; GAIA reads both.

### Adopted base (Agent Skills standard)

| Key           | Standard |     GAIA     | Notes                                                                                                                                                      |
| ------------- | :------: | :----------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`        | required |   required   | ≤64 chars, lowercase alphanumeric + single hyphens, no leading/trailing/consecutive hyphen, **must match the skill's directory name**.                     |
| `description` | required |   required   | ≤1024 chars. The trigger signal the model reads to decide relevance.                                                                                       |
| `license`     | optional |   optional   | Always `MIT` for GAIA skills (matches the repository license).                                                                                             |
| `metadata`    | optional |   optional   | Arbitrary map. GAIA's fields live under `metadata.gaia`.                                                                                                   |
| `version`     |     —    | **superset** | Top-level. The standard has no top-level `version`; GAIA adds one (Hermes/OpenClaw also carry it). A tolerated superset key — standard runtimes ignore it. |

<Warning>
  **`compatibility` and `allowed-tools` are deliberately excluded from GAIA's
  adopted base.** The Agent Skills standard defines both as optional, but they
  overlap GAIA's structured fields (`allowed-tools` ↔ `metadata.gaia.permissions`

  * `tools`; `compatibility` ↔ `metadata.gaia.requirements`) and neither Hermes nor
    OpenClaw uses them. A standard skill that *happens* to set them still parses —
    **GAIA simply ignores those two keys**; permissions and requirements come solely
    from `metadata.gaia`.
</Warning>

### The `metadata.gaia` namespace

Everything GAIA-specific is nested here. Omit the whole block and the skill is a
valid instruction-only skill (see [Off-states](#off-states-safe-floors)).

```yaml theme={null}
metadata:
  gaia:
    security_tier: verified        # verified | community | experimental (default: experimental)
    permissions:                   # <domain>:<level>[:scope] — see Permission model
      - network:read:*.brave.com
    requirements:                  # all optional; defaults = no constraint
      model: ">=7B"                # minimum parameter count (advisory)
      context: ">=8K"              # minimum context window
      python: ">=3.10"
      dependencies: [requests>=2.31]
      node_dependencies: ["@brave/brave-search-mcp-server"]
      env_vars: [BRAVE_API_KEY]
      hardware: { npu: optional, gpu_vram: ">=0GB" }
    tools:                         # tools this skill PROVIDES (its own @tool fns)
      - name: search_web
        description: Search the web for current information
        parameters:
          query: { type: string, required: true }
          max_results: { type: integer, required: false, default: 5 }
        returns: { type: object }
        atomic: false              # maps to @tool(atomic=...)
    tools_required: []             # registry tools this skill CONSUMES (recipe contract)
```

#### `tools` vs `tools_required` — never conflate them

These are two different fields with two different consumers, and collapsing them
breaks the recipe contract:

| Field            | Meaning                                                                                                                                                                                                                                                                                       | Who reads it                                                                                                                                              |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tools`          | The skill's **own** `@tool`-decorated functions (provided capability). Maps to the `@tool` decorator / `_TOOL_REGISTRY` ([`tools.py:16`](https://github.com/amd/gaia/blob/main/src/gaia/agents/base/tools.py), [`:19`](https://github.com/amd/gaia/blob/main/src/gaia/agents/base/tools.py)). | The loader, to register and validate the skill's tools.                                                                                                   |
| `tools_required` | Names of **existing registry tools** a recipe skill consumes (e.g. `query_documents`, `read_file`). The skill ships no code for them.                                                                                                                                                         | [#887](https://github.com/amd/gaia/issues/887) / [#1451](https://github.com/amd/gaia/issues/1451) — the tool-loader unions these into per-turn selection. |

The field name **`tools_required` is locked** as the cross-spec contract with
\#887/#1451. A skill may have either, both, or neither.

### Field reference

| Field                          | Type   | Required         | Description                                                                                           |
| ------------------------------ | ------ | ---------------- | ----------------------------------------------------------------------------------------------------- |
| `name`                         | string | yes              | Skill identifier; matches directory name. See [naming](#naming).                                      |
| `description`                  | string | yes              | Trigger signal (≤1024 chars).                                                                         |
| `license`                      | string | no               | Always `MIT` for GAIA skills.                                                                         |
| `version`                      | string | no (recommended) | SemVer. Top-level GAIA superset, recommended for publishing; `0.0.0` (unversioned) blocks publishing. |
| `metadata.gaia.security_tier`  | string | no               | `verified` \| `community` \| `experimental`. Default `experimental`.                                  |
| `metadata.gaia.permissions`    | list   | no               | `<domain>:<level>[:scope]` grants. Default: none.                                                     |
| `metadata.gaia.requirements`   | object | no               | Model / context / deps / env / hardware constraints. Default: none.                                   |
| `metadata.gaia.tools`          | list   | no               | Provided `@tool` declarations. Default: none (instruction-only).                                      |
| `metadata.gaia.tools_required` | list   | no               | Registry tool names consumed (recipe contract). Default: `[]`.                                        |

### Naming

Skill names follow the Agent Skills rule: `^[a-z0-9]+(-[a-z0-9]+)*$`, ≤64 chars,
and **must equal the skill's directory name** (so `web-research/SKILL.md` has
`name: web-research`). No leading, trailing, or consecutive hyphens. Names are
unique within a discovery root; precedence between roots is defined in
[Agent Skills → Discovery](/docs/spec/agent-skills#discovery-loading-and-scoping).

### Permission model

Permissions follow `<domain>:<level>` with an optional `:scope` qualifier. There
are no implicit grants — a skill declares every domain it touches.

| Domain       | Levels                  | Maps to                                                       |
| ------------ | ----------------------- | ------------------------------------------------------------- |
| `filesystem` | `read`, `write`, `none` | Local-capability domain (new; enforced by the skill sandbox). |
| `network`    | `read`, `write`, `none` | Connector scope (see bridge below).                           |
| `shell`      | `execute`, `none`       | Local-capability domain (new).                                |
| `mcp`        | `connect`, `none`       | Connector scope (MCP-server connectors).                      |
| `env`        | `read`, `none`          | Environment beyond declared `env_vars`.                       |
| `database`   | `read`, `write`, `none` | Local-capability domain (new).                                |
| `desktop`    | `control`, `none`       | Local-capability domain (new).                                |

Scopes narrow a grant: `filesystem:read:~/.gaia/data/**`,
`network:read:*.brave.com`, `shell:execute:git,npm`. An unscoped grant covers
the whole domain.

#### Bridge to the connector grant model — no parallel ledger

[Agent Skills](/docs/spec/agent-skills#scoping-into-an-agent) already states that
a skill carrying permissions is **granted to an agent reusing the connectors
per-agent grant model**. This spec makes the mapping concrete rather than
inventing a second grant system:

* `network:*` and `mcp:connect` resolve, at scope-time, to a
  `ConnectorRequirement(connector_id, scopes, reason)`
  ([`connectors/providers/base.py:23`](https://github.com/amd/gaia/blob/main/src/gaia/connectors/providers/base.py)) —
  the same frozen primitive agents already declare via
  `REQUIRED_CONNECTORS` ([`agent.py:295`](https://github.com/amd/gaia/blob/main/src/gaia/agents/base/agent.py)).
  The skill's `permissions` become the agent's connector requirements when the
  skill is scoped in.
* `filesystem:*`, `shell:*`, `database:*`, `desktop:*`, `env:*` are **new
  local-capability domains** with no connector equivalent. They are enforced by
  the skill sandbox (PROPOSED — see [Phased build](#phased-build)).

Per-agent scoping reuses the `namespaced_agent_id` keying
(`builtin:` / `custom:sha256:` / `installed:`,
[`registry.py:392`](https://github.com/amd/gaia/blob/main/src/gaia/agents/registry.py))
that already isolates agent grants today.

### Security tiers

Three tiers set the **install-time permission ceiling** and grant behavior.

| Tier           | Signing                           | At install                                                                     | Ceiling                                                |
| -------------- | --------------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------ |
| `verified`     | AMD-signed, audited               | Auto-grant, no prompt                                                          | All declared permissions pre-approved.                 |
| `community`    | Publisher-signed, automated scans | Dangerous grants (`shell:execute`, `desktop:control`, `database:write`) prompt | Below verified.                                        |
| `experimental` | None                              | Sandboxed; explicit opt-in (`--allow-experimental`)                            | Most restrictive; cannot auto-install as a dependency. |

**Promotion path:** `experimental → community → verified`. A publisher signs to
reach `community`; an AMD audit request reaches `verified`. Re-audit on every
version bump.

<Note>
  **Tiers are NOT the governance decision system.** The governance layer's
  `DecisionType = Literal["ALLOW", "REVIEW", "BLOCK"]`
  ([`governance/schemas.py:17`](https://github.com/amd/gaia/blob/main/src/gaia/governance/schemas.py))
  is a **run-time, per-action** verdict. Security tiers are an **install-time trust
  ladder** that sets the *ceiling* a skill's permissions may reach. They are
  complementary, not the same axis: a `verified` skill still has each action
  adjudicated at run time by governance. This tier system is **greenfield** — it
  does not exist in code yet.
</Note>

### Tool registration

A skill's `tools` map onto the existing decorator and registry. On load
(PROPOSED), the runtime registers each `@tool` under a `<skill-name>/<tool-name>`
namespace into `_TOOL_REGISTRY` to prevent collisions when an agent composes
multiple skills — the same namespacing
[Agent Skills](/docs/spec/agent-skills#scoping-into-an-agent) describes. The skill's
`tools.py` uses the standard `@tool` decorator unchanged:

```python theme={null}
# web-research/tools.py
from gaia.agents.base.tools import tool

@tool
def search_web(query: str, max_results: int = 5) -> dict:
    """Search the web for current information."""
    ...
```

The loader validates that every `tools` entry has a matching `@tool` function,
parameter names/types match the signature, and the return is JSON-serializable —
**failing loudly** (no partial load) on mismatch, as
[Agent Skills](/docs/spec/agent-skills#scoping-into-an-agent) requires.

### CLI

The acceptance-required trio plus the natural neighbors. **All PROPOSED** — no
`gaia skill` subcommand exists in [`cli.py`](https://github.com/amd/gaia/blob/main/src/gaia/cli.py) yet.

```bash theme={null}
gaia skill list                       # acceptance #5
gaia skill install web-research        # acceptance #5
gaia skill install some-skill --allow-experimental
gaia skill remove web-research         # acceptance #5
gaia skill info web-research
gaia skill search "web search"
gaia skill update web-research
gaia skill migrate ./hermes-skill/ --from auto   # see Compatibility
gaia skill publish ./my-skill/         # marketplace (#647)
```

### Agent UI dashboard support

Acceptance #4 requires a skills management panel. The proposed `/api/skills`
router mirrors the **existing** `/api/agents` router
([`ui/routers/agents.py`](https://github.com/amd/gaia/blob/main/src/gaia/ui/routers/agents.py):
list `:130`, detail `:174`, export `:184`, import `:222`) — the same
list/detail/install/remove shape, so the panel reuses the agents-panel
conventions rather than inventing new ones.

```
GET    /api/skills                 # list installed skills (+ tier, version)   PROPOSED
GET    /api/skills/{name}          # skill detail (manifest, permissions)      PROPOSED
POST   /api/skills/install         # install from registry/path                PROPOSED
DELETE /api/skills/{name}          # remove                                    PROPOSED
```

There is **no `/api/skills` router today** — the dashboard is greenfield and
degrades to empty until the loader lands (see [Off-states](#off-states-safe-floors)).

### Cross-format compatibility & migration

Three formats, one namespace pattern. GAIA reads the standard base directly and
treats Hermes/OpenClaw as **migration sources**, not runtime targets.

| Format                                                      | Where its fields live         | GAIA support                                                 |
| ----------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------ |
| **Agent Skills** ([agentskills.io](https://agentskills.io)) | base + (GAIA) `metadata.gaia` | **Native, lossless.** A bare standard skill loads unchanged. |
| **Hermes** (Nous Research)                                  | `metadata.hermes`             | Migrate via `gaia skill migrate --from hermes`.              |
| **OpenClaw / ClawHub**                                      | `metadata.openclaw`           | Migrate via `gaia skill migrate --from openclaw`.            |

A single tool — `gaia skill migrate --from {hermes,openclaw,auto}` (auto-detect
keys on the `metadata.<vendor>` map) — reads the foreign namespace and writes a
`metadata.gaia` block. **Every migrated skill lands `experimental`**, re-earning
trust. Migration emits a report of fields needing manual review.

<Warning>
  **No runtime adapter in v1.** The prior draft promised an `OpenClawAdapter` that
  wrapped foreign handlers in `@tool` at load time
  (`from gaia.skills.openclaw import OpenClawAdapter`). **That is retracted** —
  v1 is migration-only. A runtime adapter is deferred to a later phase; do not
  build against `OpenClawAdapter`.
</Warning>

### Relationship to neighbors

* **[Agent Skills](/docs/spec/agent-skills)** — owns the architecture and integration
  surface (discovery roots, progressive disclosure, scoping, the
  skill/tool/agent distinction). This doc owns the field grammar. Where they
  overlap, that spec is canonical for the compatibility surface and this one for
  the schema; the two are reconciled (see
  [Correcting the prior spec](#correcting-the-prior-spec)).
* **Agent Manifest ([#462](https://github.com/amd/gaia/issues/462))** — a
  `gaia-agent.yaml` references skills by name + version range; `SKILL.md` is the
  skill-level complement. The `skills:` block and its resolution live in
  [Agent Skills → Agent Hub integration](/docs/spec/agent-skills#agent-hub-integration).
* **Agent bundles** — skill packaging relates to the existing agent bundle format
  (`.zip` + `bundle.json`, `BUNDLE_FORMAT_VERSION = 1`,
  [`export_import.py:40`](https://github.com/amd/gaia/blob/main/src/gaia/installer/export_import.py)).
* **Builder template** — scaffolds `agent.py` today
  ([`builder/template.py`](https://github.com/amd/gaia/blob/main/src/gaia/agents/builder/template.py));
  emitting `SKILL.md` is a future extension, not current behavior.
* **OEM bundling ([#648](https://github.com/amd/gaia/issues/648))** — needs a
  stable definition of "a skill" to pre-configure hardware SKUs. A SKU pre-bundles
  skills as `verified`-tier entries in a discovery root; the directory anatomy and
  tier defaults this doc fixes *are* that definition.

### Example skills

Six worked examples. The three for existing agents (acceptance #6) declare only
tool names that exist in the current registry. All parse as YAML; tool skills
round-trip against their `tools.py`.

<AccordionGroup>
  <Accordion title="1. Minimal instruction-only skill (bare standard)">
    Proves a bare Agent Skills `SKILL.md` loads with no GAIA fields — defaulting to
    `experimental`, no tools, no permissions.

    ```yaml theme={null}
    ---
    name: incident-review
    description: Walk through a production incident postmortem. Use when the user mentions an outage, incident, or postmortem.
    ---

    # Incident Review

    1. Establish the timeline from first alert to resolution.
    2. Separate root cause from contributing factors.
    3. Draft action items with owners — never "the team".
    ```
  </Accordion>

  <Accordion title="2. Tool skill in the new shape (web-research)">
    The restructured schema: standard base + `metadata.gaia`.

    ```yaml theme={null}
    ---
    name: web-search
    description: Search the web via the Brave Search API. Use when the user asks about current events or external facts.
    license: MIT
    version: 1.0.0
    metadata:
      gaia:
        security_tier: verified
        permissions:
          - network:read:*.brave.com
        requirements:
          python: ">=3.10"
          dependencies:
            - requests>=2.31
          env_vars:
            - BRAVE_API_KEY
        tools:
          - name: search_web
            description: Search the web for current information
            parameters:
              query: { type: string, required: true }
              max_results: { type: integer, required: false, default: 5 }
            returns: { type: object }
            atomic: false
    ---

    # Web Search

    A self-contained Brave Search wrapper — `search_web` is this skill's own
    `@tool`, backed by the skill's `tools.py`.
    ```
  </Accordion>

  <Accordion title="3. Recipe skill with tools_required (the #887/#1451 contract)">
    A distilled procedure that consumes existing registry tools. Each
    `tools_required` name resolves against a real registry tool (`query_documents`
    from `RAGToolsMixin`, `read_file` from `FileIOToolsMixin`; `remember` from the
    tool-loader CORE set).

    ```yaml theme={null}
    ---
    name: triage-support-ticket
    description: Triage an inbound support ticket end to end. Use when the user pastes a support ticket or asks to triage one.
    version: 0.2.0
    metadata:
      gaia:
        security_tier: experimental
        tools_required:
          - query_documents
          - read_file
          - remember
    ---

    # Triage a Support Ticket

    1. Pull matching policy docs with `query_documents`.
    2. Read any attached log with `read_file`.
    3. Record the disposition with `remember` for follow-up.
    ```
  </Accordion>

  <Accordion title="4a. rag-search (from RAGToolsMixin)">
    Acceptance #6 — a skill mapping the `rag` mixin's real tools.

    ```yaml theme={null}
    ---
    name: rag-search
    description: Search and answer over indexed documents. Use when the user asks about the contents of uploaded files.
    version: 1.0.0
    metadata:
      gaia:
        security_tier: verified
        permissions:
          - filesystem:read
        tools:
          - name: query_documents
            description: Answer a question over all indexed documents
            parameters:
              query: { type: string, required: true }
            returns: { type: object }
          - name: search_indexed_chunks
            description: Return the top matching chunks for a pattern
            parameters:
              pattern: { type: string, required: true }
            returns: { type: object }
          - name: list_indexed_documents
            description: List documents currently in the index
            parameters: {}
            returns: { type: object }
    ---

    # RAG Search

    Use `query_documents` for direct answers; `search_indexed_chunks` to inspect
    evidence; `list_indexed_documents` to see what is available.
    ```
  </Accordion>

  <Accordion title="4b. web-research (from BrowserToolsMixin)">
    Acceptance #6 — the `browser` mixin's real tools (`search_web`, `fetch_page`,
    `download_file`).

    ```yaml theme={null}
    ---
    name: web-research
    description: Research the open web. Use when the user asks about current events or facts not in the documents.
    version: 1.0.0
    metadata:
      gaia:
        security_tier: verified
        permissions:
          - network:read
        tools:
          - name: search_web
            description: Search the web for current information
            parameters:
              query: { type: string, required: true }
            returns: { type: object }
          - name: fetch_page
            description: Fetch and extract the readable text of a URL
            parameters:
              url: { type: string, required: true }
            returns: { type: object }
          - name: download_file
            description: Download a file from a URL to local disk
            parameters:
              url: { type: string, required: true }
            returns: { type: object }
    ---

    # Web Research

    Search first, then fetch the best results; download only when the user asks for
    the file itself.
    ```
  </Accordion>

  <Accordion title="4c. file-operations (from FileIOToolsMixin)">
    Acceptance #6 — the `file_io` mixin's real tools.

    ```yaml theme={null}
    ---
    name: file-operations
    description: Read, write, and edit files on the local workspace. Use when the user asks to inspect or modify files.
    version: 1.0.0
    metadata:
      gaia:
        security_tier: community
        permissions:
          - filesystem:read
          - filesystem:write:./**
        tools:
          - name: read_file
            description: Read the contents of a file
            parameters:
              file_path: { type: string, required: true }
            returns: { type: object }
          - name: write_file
            description: Write content to a file
            parameters:
              file_path: { type: string, required: true }
              content: { type: string, required: true }
            returns: { type: object }
          - name: edit_file
            description: Replace a span of text in an existing file
            parameters:
              file_path: { type: string, required: true }
              old_content: { type: string, required: true }
              new_content: { type: string, required: true }
            returns: { type: object }
    ---

    # File Operations

    Read before you write; prefer `edit_file` for in-place changes over rewriting a
    whole file with `write_file`.
    ```
  </Accordion>

  <Accordion title="5. Hermes skill + its metadata.gaia migration">
    A Hermes skill (left) and what `gaia skill migrate --from hermes` produces
    (right) — the `metadata.hermes` fields become `metadata.gaia`, and the result
    lands `experimental`.

    ```yaml theme={null}
    # BEFORE — Hermes
    ---
    name: pdf-extract
    description: Extract structured data from a PDF.
    version: 1.0.0
    metadata:
      hermes:
        category: documents
        requires:
          tools: [read_file]
    ---

    # Extract from PDF
    ...
    ```

    ```yaml theme={null}
    # AFTER — gaia skill migrate --from hermes
    ---
    name: pdf-extract
    description: Extract structured data from a PDF.
    version: 1.0.0
    metadata:
      gaia:
        security_tier: experimental
        tools_required:
          - read_file
    ---

    # Extract from PDF
    ...
    ```
  </Accordion>

  <Accordion title="6. OpenClaw skill + its migration">
    An OpenClaw skill and its migrated form. `metadata.openclaw` requirements map to
    `metadata.gaia.requirements`; trust resets to `experimental`.

    ```yaml theme={null}
    # BEFORE — OpenClaw
    ---
    name: git-status
    description: Summarize the working tree status.
    version: 0.3.0
    metadata:
      openclaw:
        requires:
          bins: [git]
    ---

    # Git Status
    ...
    ```

    ```yaml theme={null}
    # AFTER — gaia skill migrate --from openclaw
    ---
    name: git-status
    description: Summarize the working tree status.
    version: 0.3.0
    metadata:
      gaia:
        security_tier: experimental
        permissions:
          - shell:execute:git
    ---

    # Git Status
    ...
    ```
  </Accordion>
</AccordionGroup>

***

## Off-states (safe floors)

Every degraded condition lands on a conservative, well-defined floor — nothing
breaks because a GAIA feature is absent.

| Condition                                                  | Floor behavior                                                                                                                                                                                                                                                                                                                                                                               |
| ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Bare standard skill** (only `name` + `description`)      | Loads as an **instruction-only** skill: `security_tier: experimental`, no tools, no permissions. The most restrictive defaults. Matches [Agent Skills → compatibility rule](/docs/spec/agent-skills#manifest-format).                                                                                                                                                                             |
| **No `metadata.gaia` block**                               | All GAIA fields take their omitted-defaults (above). A standard runtime ignores `metadata.gaia` entirely → lossless both directions.                                                                                                                                                                                                                                                         |
| **`compatibility` / `allowed-tools` present**              | Ignored (not part of GAIA's adopted base). The skill still parses.                                                                                                                                                                                                                                                                                                                           |
| **`tools_required` names a tool unknown to the framework** | **Fails loudly** at validation — an actionable error names the unresolvable tool, matching the `tools`↔`tools.py` and tier-ceiling checks and GAIA's fail-loudly policy. (A name that is *valid but simply not active in the current agent's registry* is scoping, not a defect: it is omitted from selection and logged, never silently invented — see [Open question 1](#open-questions).) |
| **Loader not yet shipped** (today)                         | The format is an inert contract — nothing reads it, so nothing can misbehave. `/api/skills`, the registry, and `migrate` degrade to absent.                                                                                                                                                                                                                                                  |
| **Tier signal unavailable**                                | Falls to `experimental` — the most-restrictive tier — never to a more-permissive default.                                                                                                                                                                                                                                                                                                    |

**Future-gated phases are additive with precedence.** The `tools_required`
signal that #1451 consumes returns `[]` cleanly until #887 lands
([`tool-loader.mdx`](/docs/plans/tool-loader#part-3-skill-driven-signal-gated-on-887)),
so a recipe skill authored today is valid but inert until its consumer ships —
it never blocks or errors.

***

## Correcting the prior spec

This document **revises** an earlier draft of `skill-format.mdx`. The most
important correction:

> **The base standard is Agent Skills ([agentskills.io](https://agentskills.io)),
> not OpenClaw.** The prior draft framed "OpenClaw / ClawHub" as *the* external
> standard to be compatible with. In fact agentskills.io (as used by Claude Code)
> is the base GAIA adopts; OpenClaw is just **one of several compatible
> third-party formats**, alongside Hermes. This reconciles `skill-format.mdx`
> with [Agent Skills](/docs/spec/agent-skills), which had already flagged
> "OpenClaw/ClawHub" as a placeholder from an earlier draft.

The second structural correction: **GAIA-specific fields move from the top level
into `metadata.gaia`.** The prior draft put `permissions` / `security_tier` /
`requirements` / `tools` at the top level, which collides with the standard's
namespace and breaks lossless cross-runtime parsing. Nesting them under
`metadata.gaia` mirrors the convergent prior art (Hermes `metadata.hermes`,
OpenClaw `metadata.openclaw`).

<Warning>
  **Retractions — do not build against these:**

  * **`OpenClawAdapter` runtime adapter is dropped from v1.** Compatibility is
    migration-only (`gaia skill migrate`); the runtime adapter is deferred.
  * **The flat top-level schema is superseded.** `permissions`, `security_tier`,
    `requirements`, and `tools` are now under `metadata.gaia`. Top-level `version`
    is the *only* GAIA superset key outside `metadata`.
  * **`compatibility` and `allowed-tools` are not part of GAIA's base.** The prior
    reliance on `allowed-tools` for permission scoping is removed; permissions come
    from `metadata.gaia.permissions`.
  * **Every runtime symbol is greenfield.** `SkillManager`, `gaia.skills`,
    `load_skill()`, `~/.gaia/skills/`, the registry REST API, and `/api/skills` do
    **not** exist in code (verified absent on `main`). They are a contract for
    unwritten code, marked PROPOSED throughout.
</Warning>

***

## KPIs

A format contract is judged by **conformance and losslessness**, not runtime
speed. The bar:

| KPI                             | Type                | Target                                                                                                                                                        |
| ------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Cross-spec field-name match** | Headline (contract) | `tools_required` (and every other emitted field) is byte-identical across #887, #1451, and this spec — zero drift.                                            |
| **Lossless round-trip**         | Correctness         | A bare agentskills.io skill loads in GAIA unchanged; a GAIA skill's standard fields parse in a standard runtime with `metadata.gaia` ignored, no parse break. |
| **Migration fidelity**          | Correctness         | `gaia skill migrate` output validates against this schema and lands `experimental`.                                                                           |
| **No hallucinated runtime**     | Grounding           | Every cited symbol resolves on `main` or is marked PROPOSED. (Met by this revision.)                                                                          |
| **Example validity**            | Grounding           | Every example parses as YAML; each tool skill's `tools` block round-trips against its `tools.py`.                                                             |
| **Acceptance coverage**         | Completeness        | 100% of #691's acceptance criteria map to a section (see [Traceability](#acceptance-criteria-traceability)).                                                  |

***

## Phased build

The format (Phase 0) is decided in this PR; the runtime is greenfield and ships
in additive phases. Each phase holds the prior floor until it lands.

### Phase 0 — Format contract (this revision)

**Success criteria:**

* Schema decided: adopted base + `metadata.gaia`; `tools` vs `tools_required`
  separated; `compatibility`/`allowed-tools` excluded.
* [Agent Skills](/docs/spec/agent-skills) reconciled — mapping table nests
  `metadata.gaia.*`, the placeholder Note becomes a Division-of-authority Note, and
  `allowed-tools`/`compatibility` are marked excluded.
* All example skills parse; the three acceptance-#6 skills use only real
  registry tool names.
* Traceability covers 100% of #691 acceptance criteria.

### Phase 1 — Loader, validator, CLI core (PROPOSED)

`gaia.skills` parses + validates `metadata.gaia`, registers `tools` under the
`<skill>/<tool>` namespace into `_TOOL_REGISTRY`, and ships
`gaia skill list|install|remove`. Discovery roots per
[Agent Skills](/docs/spec/agent-skills#discovery-loading-and-scoping).

**Success criteria:**

* A tool skill loads and its tools register and call.
* A bare standard skill loads instruction-only.
* Validation fails **loudly** on a tools/`tools.py` mismatch or a permission that
  exceeds the tier ceiling — no partial load.

### Phase 2 — Permission enforcement + tier ceilings + connector bridge (PROPOSED)

`<domain>:<level>` enforced by the sandbox; `network`/`mcp` permissions resolve
to `ConnectorRequirement` at scope-time; tier ceiling enforced; `experimental`
sandbox.

**Success criteria:**

* A skill requesting a permission above its tier ceiling fails to load.
* A `network:*` / `mcp:connect` permission produces the matching connector grant
  requirement; `filesystem`/`shell`/`database`/`desktop` route to the sandbox.

### Phase 3 — Agent UI dashboard + migration (PROPOSED)

`/api/skills` mirroring `/api/agents`; the skills management panel; `gaia skill
migrate --from {hermes,openclaw,auto}`.

**Success criteria:**

* The panel lists installed skills with tier + version and supports
  install/remove (acceptance #4).
* `migrate` output validates and lands `experimental` for Hermes and OpenClaw
  inputs.

### Phase 4 — Marketplace + consumer wiring (PROPOSED; #647 / #887 / #1451)

Publish/registry REST; #887 emits conformant `SKILL.md`; #1451 unions
`tools_required`.

**Success criteria:**

* \#887-synthesized files validate against this schema unchanged.
* \#1451 unions a matched skill's `tools_required` **ahead of** semantic results
  (the contract in [`tool-loader.mdx`](/docs/plans/tool-loader#part-3-skill-driven-signal-gated-on-887)).

***

## Open questions

The five design forks (base standard, `metadata.gaia` nesting, top-level
`version`, migration-only v1, excluding `compatibility`/`allowed-tools`) are
**locked by the maintainer** and are recorded as settled above. What remains are
implementation-level questions for whoever builds the runtime:

1. **`tools_required` validation timing.** Fail-vs-skip is *not* open — GAIA's
   fail-loudly policy settles it: a name **unknown to the framework** is a manifest
   defect and fails loudly; a name **valid but inactive** in the current agent's
   registry is scoping (omitted + logged, not an error). The genuine open nuance is
   *when* the unknown-name check runs — at install against a static tool catalog,
   or deferred — since the active registry is assembled dynamically from mixins and
   other skills, so the full tool universe may not be known at install time.
   Affects #1451 robustness.
2. **Skill→skill dependencies.** The prior draft allowed a skill to depend on
   other skills (`requirements.skills`). Keep it under
   `metadata.gaia.requirements`, or defer dependency resolution to the
   marketplace (#647)?
3. **`/api/skills` install sources.** Registry-only, or also local path / URL?
   The latter widens the install-time security surface.
4. **Body-injection scanning.** Static scanning of instruction bodies for
   injection patterns at import — required for `community`+, advisory for
   `experimental`? (Also open in
   [Agent Skills → Open questions](/docs/spec/agent-skills#open-questions); resolve in
   one place.)
5. **`docs/spec/` relocation.** #691 acceptance says "documented in
   `docs/spec/`"; this doc stays in `docs/plans/` until the loader ships. Does the
   move to `docs/spec/` (and the `docs.json` update) happen with Phase 1, or
   earlier?

***

## Current state of the code

The format is grounded on real primitives; the skill runtime is **entirely
greenfield**.

| Area                                                                                                                           | Symbol / fact                                                    | `file:line`                                        | State                                        |
| ------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------- | -------------------------------------------------- | -------------------------------------------- |
| Tool registry                                                                                                                  | `_TOOL_REGISTRY: dict[str, dict]`                                | `agents/base/tools.py:16`                          | **Exists**                                   |
| Tool decorator                                                                                                                 | `@tool(func, *, atomic, display_label, timeout, …)`              | `agents/base/tools.py:19`                          | **Exists**                                   |
| Mixin map                                                                                                                      | `KNOWN_TOOLS` (rag, browser, file\_io, …)                        | `agents/registry.py:38`                            | **Exists** — source for the 3 example skills |
| Agent base                                                                                                                     | `Agent`, `_compose_system_prompt`, `_get_system_prompt`          | `agents/base/agent.py:245`, `:591`, `:669`         | **Exists**                                   |
| Connector grant                                                                                                                | `ConnectorRequirement(connector_id, scopes, reason)`             | `connectors/providers/base.py:23`                  | **Exists** — permission bridge               |
| Required connectors                                                                                                            | `REQUIRED_CONNECTORS: ClassVar[...]`                             | `agents/base/agent.py:295`                         | **Exists**                                   |
| Governance                                                                                                                     | `DecisionType = Literal["ALLOW","REVIEW","BLOCK"]`               | `governance/schemas.py:17`                         | **Exists** — run-time, *not* tiers           |
| Per-agent identity                                                                                                             | `namespaced_agent_id` (`builtin:`/`custom:sha256:`/`installed:`) | `agents/registry.py:392`                           | **Exists** — scoping precedent               |
| Default model                                                                                                                  | `DEFAULT_MODEL_NAME = "Gemma-4-E4B-it-GGUF"`                     | `llm/lemonade_client.py:119`                       | **Exists**                                   |
| Model tiers / device                                                                                                           | `build_model_tiers()`, `DeviceConfig(ctx_size=…)`                | `agents/registry.py:335`, `:227`                   | **Exists** — `requirements` references these |
| Agents UI router                                                                                                               | `/api/agents` list/detail/export/import                          | `ui/routers/agents.py:130`, `:174`, `:184`, `:222` | **Exists** — `/api/skills` mirrors it        |
| Bundle format                                                                                                                  | `.zip` + `bundle.json`, `BUNDLE_FORMAT_VERSION = 1`              | `installer/export_import.py:40`                    | **Exists**                                   |
| Builder template                                                                                                               | scaffolds `agent.py`, emits no `SKILL.md`                        | `agents/builder/template.py`                       | **Exists**                                   |
| **Skill loader / `SkillManager` / `gaia.skills` / `load_skill` / `gaia skill` CLI / `~/.gaia/skills/` loader / `/api/skills`** | —                                                                | **NOT FOUND**                                      | **Greenfield — PROPOSED**                    |

***

## Dependencies

**Blocking: none.** This is a foundational format contract; its design inputs are
external standards plus the in-repo drafts.

**Design inputs:** [Agent Skills](https://agentskills.io) (base), Hermes
(`metadata.hermes`), OpenClaw (`metadata.openclaw`), Claude Code (reference
impl); in-repo [Agent Skills](/docs/spec/agent-skills) (architecture / compatibility
surface) and [`tool-loader.mdx`](/docs/plans/tool-loader) Part 3 (the `tools_required`
contract).

**Downstream consumers.** The features whose contract this format must satisfy. A
*closed* tracking issue means that design is settled and already references this
format — not that the dependency is gone.

| Consumer                                                            | What it needs                                                                    | Tracking issue          |
| ------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ----------------------- |
| [#887](https://github.com/amd/gaia/issues/887) skill auto-synthesis | *Emits* `SKILL.md` — the exact frontmatter, esp. `tools_required`.               | open                    |
| [#553](https://github.com/amd/gaia/issues/553) self-improving agent | Skill extraction *emits* conformant `SKILL.md` — same producer contract as #887. | open                    |
| [#1451](https://github.com/amd/gaia/issues/1451) tool-loader Part 3 | *Reads* `tools_required` to union into per-turn tool selection.                  | open (gated on #887)    |
| [#648](https://github.com/amd/gaia/issues/648) OEM bundling         | A definition of "a skill" to pre-bundle SKU defaults.                            | open                    |
| [#647](https://github.com/amd/gaia/issues/647) marketplace          | The format + the three tiers to publish/promote.                                 | closed (design settled) |
| [#462](https://github.com/amd/gaia/issues/462) Agent Manifest       | A skill-level complement to `gaia-agent.yaml`.                                   | closed (design settled) |

***

## Acceptance-criteria traceability

Every acceptance criterion from [#691](https://github.com/amd/gaia/issues/691),
verbatim, mapped to its section and what it guarantees a consumer.

| #691 acceptance criterion                                      | Section                                                                                          | What it guarantees                                                                               |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| ☐ SKILL.md spec documented in `docs/spec/`                     | This doc (kept in `docs/plans/` until the loader ships — see [Open question 5](#open-questions)) | A single authoritative field grammar.                                                            |
| ☐ Permission model defined with granular `domain:level` syntax | [Permission model](#permission-model)                                                            | `<domain>:<level>:scope` grammar + the `ConnectorRequirement` bridge — no parallel grant ledger. |
| ☐ Security tiers defined with promotion path                   | [Security tiers](#security-tiers)                                                                | Three install-time tiers + `experimental→community→verified`, distinct from run-time governance. |
| ☐ Agent UI configuration dashboard has skills management panel | [Agent UI dashboard support](#agent-ui-dashboard-support)                                        | A `/api/skills` shape mirroring the live `/api/agents` panel (PROPOSED).                         |
| ☐ CLI: `gaia skill list`, `install`, `remove`                  | [CLI](#cli)                                                                                      | The required trio, specified (PROPOSED).                                                         |
| ☐ Example skills written for 3 existing agents                 | [Example skills](#example-skills) 4a–4c                                                          | `rag-search`, `web-research`, `file-operations` — each using only real registry tool names.      |
