Conversation
Prototype of the skill-set layering discussed with agentskills.io: - AI Catalog (/.well-known/ai-catalog.json) entries typed application/agent-skills+json point at an agentskills PR #254 discovery index and represent an installable skill set. - The optional io.hermes.skill-set extension carries set-level usage intent: a suggested load-alias command and a shared instruction preamble. Clients that ignore the extension still install the correct set. - tools/skill_set_catalog.py implements the client: $schema gating, required sha256 digest verification, skill-md + archive (.tar.gz/.zip) artifacts, and #254 archive-safety rules (traversal/absolute-path/ link rejection, decompression caps). - hermes skills install-set <url> installs every member through the existing quarantine -> scan -> install pipeline, then creates the /<name> skill bundle so the whole set loads in one turn. - scripts/publish_skill_set.py is the publisher-side counterpart: builds the static .well-known tree (catalog + index + artifacts) from local skill directories with byte-stable archives.
૮ >ﻌ< ა ci reviewran on 665129c
|
jonathanhefner
left a comment
There was a problem hiding this comment.
Amazing! ❤️
(For any onlookers, #254 refers to agentskills/agentskills#254 rather than #254.)
Codex found a few minor issues that I wanted to bubble up:
-
There is a redirect + URL resolution issue for skill set manifest files. For example:
- An AI Catalog entry points to
https://example.com/.well-known/agent-skills/index.json. - That URL redirects to
https://cdn.example.com/releases/v2/index.json. - The retrieved skill set manifest contains
"url": "review/SKILL.md". - RFC 3986 resolution produces
https://cdn.example.com/releases/v2/review/SKILL.md. - Hermes instead produces
https://example.com/.well-known/agent-skills/review/SKILL.md.
- An AI Catalog entry points to
-
Archive type is currently being determined by URL file extension (inside the skill set manifest file). Per agentskills/agentskills#254, it should check the
Content-Typeheader before falling back to the URL file extension. -
This implementation supports
urlin AI catalog entries but notdata. Per https://github.com/Agent-Card/ai-catalog/blob/11ff6bb7541f10c3f06f740fc9ebb74bb95dca99/specification/ai-catalog.md#L239-L247, AI Catalog entries can have eitherurlor inlinedata. (Not a blocker, but you may want to consider supportingdataas well.)
…ion, inline data Follow-ups from jonathanhefner's review on the skill-set prototype: - Relative member URLs now resolve per RFC 3986 against the URL the index/catalog was ACTUALLY retrieved from (post-redirect), so an index that redirects to a CDN resolves its members against the CDN location, not the original well-known path. - Archive format detection checks the Content-Type header first (application/gzip, application/zip, + common aliases) and only falls back to the URL file extension when the header is absent or generic, per agentskills #254. - AI Catalog entries carrying inline 'data' instead of 'url' are now supported for both skill-set entries and nested sub-catalogs; inline indexes get the same $schema gating, and their relative member URLs resolve against the catalog's retrieved location.
|
Thanks for the careful review — all three are addressed in 665129c:
41 tests green. Happy to keep iterating as #254 / the extension shape settle. |
Summary
hermes skills install-set <url>installs a published group of skills in one command and creates the/<name>bundle alias that loads them together — a working prototype of the skill-set layering discussed with agentskills.io (agentskills PR #254 + AI Catalog).The layering:
/.well-known/ai-catalog.json) — an entry typedapplication/agent-skills+jsonpoints at a skill discovery index and represents an installable set.{"$schema", "skills": [{name, description, type: skill-md|archive, url, digest}]}.$schemagating, required sha256 digests, and archive-safety rules implemented per the spec draft.io.hermes.skill-setextension (namespaced AI Catalog entry metadata) — carries set-level usage intent: a suggested load-aliascommandand a sharedinstructionpreamble. Clients that don't recognize the extension still install the correct set; they only miss the alias/preamble sugar.Changes
tools/skill_set_catalog.py(new): catalog/index client —$schemaallow-list (warn + stop on unknown, per feat(agent): use main model for context compression when no override is set #254), requiredsha256:digest verification,skill-md+archiveartifacts (.tar.gz/.zip), archive safety (traversal/absolute-path/symlink/hardlink rejection, decompression-bomb caps, SKILL.md-at-root check), one-level sub-catalog nesting. All HTTP through the existing SSRF-guarded fetcher.hermes_cli/skills_hub.py:do_install_set()— resolves origin → catalog → set → members, installs each member through the existing quarantine → security-scan → install pipeline (lock-file provenance included), then creates the skill-bundle alias from the extension.hermes_cli/subcommands/skills.py:hermes skills install-set <url> [--set NAME] [--no-alias] [--force] [-y].scripts/publish_skill_set.py(new): publisher-side counterpart — builds the static.well-known/tree (catalog + index + artifacts, byte-stable tar.gz for digest-friendly caching) from local skill directories.tests/tools/test_skill_set_catalog.py(new): 31 tests.Validation
$schemaunknown/absentdo_install_set()against a served catalog — 2 skills installed via quarantine+scan, lock entries with digests,/backend-devalias created andbuild_bundle_invocation_message()loads both skills with the shared instructionscripts/run_tests.shtargeted (new + sibling skills-hub/bundles/subparser files)Infographic