metadata is specified as string values, but a shipping runtime stores nested maps and booleans there
Summary
The specification says metadata is "a map from string keys to string values". At least one shipping runtime stores a nested structure with non-string values there, and documents doing so. A skill that follows the runtime cannot satisfy the specification's stated type, and a skill that satisfies the type cannot use the runtime's features.
What the runtime documents
Hermes (hermes-agent.nousresearch.com), Creating Skills, read 2026-08-21:
metadata:
hermes:
tags: [Category, Subcategory, Keywords]
related_skills: [other-skill-name]
requires_toolsets: [web]
requires_tools: [web_search]
fallback_for_toolsets: [browser]
config: # a list of maps
- key: my.setting
description: "What this setting controls"
default: "sensible-default"
blueprint: # a map, with a boolean in it
schedule: "0 9 * * *"
deliver: origin
no_agent: false
required_environment_variables: # a list of maps
- name: MY_API_KEY
prompt: "Enter your API key"None of that is decoration. requires_toolsets and fallback_for_tools decide whether the skill appears in the system prompt at all; blueprint makes the skill a schedulable automation and flows through that runtime's whole publish/install/index pipeline; config and required_environment_variables drive its setup prompts.
no_agent: false is a boolean, config is a list of maps, and metadata.hermes is itself a map inside metadata. A string-valued metadata can hold none of them.
Why this is worth a specification change rather than a runtime one
metadata's own description is the extension point — "Clients can use this to store additional properties not defined by the Agent Skills spec". Restricting the values to strings means a client's additional properties must be flat and textual, which is a stronger constraint than "not defined by the spec" implies and than the extension point is for. The alternative available to a client today is to put its data in top-level fields instead, which is worse for everyone: it collides with future specification fields and it is what the validator's "Unexpected fields in frontmatter" is there to catch.
What we observed, for whatever it is worth as a data point
We ship seven SKILL.md files across seven runtimes and ran skills-ref validate against all of them for the first time on 2026-08-20. The Hermes one carries the nested map above.
The validator does not enforce the string-value rule — with a nested metadata.hermes.tags list present, validate() reports only the unexpected top-level fields and says nothing about metadata. So the constraint is in the prose and not in the reference implementation, which is a third state worth resolving in one direction or the other: either the prose should widen, or the validator should enforce what it says and every Hermes skill becomes invalid.
We are not asking for a decision in our favour — we would be equally served by a clear no, flatten it, because then the runtime's own documentation is the thing to change and we can say so to them. What does not work is the current state, where the prose, the validator and a shipping client each say something different.
One further note on the same paragraph: strictyaml refuses flow style categorically, so platforms: [linux, macos, windows] — valid YAML that the runtime's own documentation uses in every example — fails to parse before validation begins. That is a validator-implementation choice rather than anything the specification requires, and it is worth saying out loud in the reference implementation's README, because the error message ("Found ugly disallowed JSONesque flow mapping") reads like a specification rule.
Source: agentskills/agentskills