Skip to main content
Grounds on (exists today): src/gaia/agents/base/tools.py (@tool, _TOOL_REGISTRY) · src/gaia/agents/registry.py (KNOWN_TOOLS, namespaced_agent_id) · src/gaia/connectors/providers/base.py (ConnectorRequirement) · 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.
Component: the SKILL.md field grammar — the on-disk contract for GAIA’s skill ecosystem (issue #691).Module: gaia.skillsPROPOSED, 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 spec owns the integration surface (discovery, scoping, progressive disclosure); this document is authoritative for the field grammar.Target consumers: #887 (skill auto-synthesis), #553 (self-improving agent), #1451 (tool-loader Part 3), #647 (skill marketplace), #648 (OEM bundling), #462 (Agent Manifest).

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) 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 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 (skill auto-synthesis) and #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 (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.
  • #647 (marketplace) and #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: 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)

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-toolsmetadata.gaia.permissions
  • tools; compatibilitymetadata.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.

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).

tools vs tools_required — never conflate them

These are two different fields with two different consumers, and collapsing them breaks the recipe contract: 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

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.

Permission model

Permissions follow <domain>:<level> with an optional :scope qualifier. There are no implicit grants — a skill declares every domain it touches. 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 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) — the same frozen primitive agents already declare via REQUIRED_CONNECTORS (agent.py:295). 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).
Per-agent scoping reuses the namespaced_agent_id keying (builtin: / custom:sha256: / installed:, registry.py:392) that already isolates agent grants today.

Security tiers

Three tiers set the install-time permission ceiling and grant behavior. Promotion path: experimental → community → verified. A publisher signs to reach community; an AMD audit request reaches verified. Re-audit on every version bump.
Tiers are NOT the governance decision system. The governance layer’s DecisionType = Literal["ALLOW", "REVIEW", "BLOCK"] (governance/schemas.py:17) 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.

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 describes. The skill’s tools.py uses the standard @tool decorator unchanged:
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 requires.

CLI

The acceptance-required trio plus the natural neighbors. All PROPOSED — no gaia skill subcommand exists in cli.py yet.

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: 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.
There is no /api/skills router today — the dashboard is greenfield and degrades to empty until the loader lands (see Off-states).

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. 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.
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.

Relationship to neighbors

  • 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).
  • Agent Manifest (#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.
  • Agent bundles — skill packaging relates to the existing agent bundle format (.zip + bundle.json, BUNDLE_FORMAT_VERSION = 1, export_import.py:40).
  • Builder template — scaffolds agent.py today (builder/template.py); emitting SKILL.md is a future extension, not current behavior.
  • OEM bundling (#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.
Proves a bare Agent Skills SKILL.md loads with no GAIA fields — defaulting to experimental, no tools, no permissions.
The restructured schema: standard base + metadata.gaia.
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).
Acceptance #6 — a skill mapping the rag mixin’s real tools.
Acceptance #6 — the browser mixin’s real tools (search_web, fetch_page, download_file).
Acceptance #6 — the file_io mixin’s real tools.
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.
An OpenClaw skill and its migrated form. metadata.openclaw requirements map to metadata.gaia.requirements; trust resets to experimental.

Off-states (safe floors)

Every degraded condition lands on a conservative, well-defined floor — nothing breaks because a GAIA feature is absent. Future-gated phases are additive with precedence. The tools_required signal that #1451 consumes returns [] cleanly until #887 lands (tool-loader.mdx), 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), 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, 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).
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.

KPIs

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

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 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. 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).

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; 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.

Dependencies

Blocking: none. This is a foundational format contract; its design inputs are external standards plus the in-repo drafts. Design inputs: Agent Skills (base), Hermes (metadata.hermes), OpenClaw (metadata.openclaw), Claude Code (reference impl); in-repo Agent Skills (architecture / compatibility surface) and tool-loader.mdx 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.

Acceptance-criteria traceability

Every acceptance criterion from #691, verbatim, mapped to its section and what it guarantees a consumer.