You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Makes a skill (a SKILL.md + scripts bundle, like the ones embedded in the obol binary) a first-class sellable and ratable unit on the stack, in two modes:
Share mode — sell the bundle bytes. New ServiceOffer type=skill: the gzipped bundle lives in a ConfigMap, the controller validates it (existence, 900 KB cap, sha256 match) and renders a restricted-PSS busybox httpd serving bundle.tar.gz + skill.json behind the standard x402 payment gate at /services/<name>/*.
Service mode — sell the skill's execution: obol sell skill --as-service --agent <a> is thin sugar over the existing type=agent offer path, carrying the skill identity in registration metadata. Zero new controller surface.
Ratings and integrity ride ERC-8004 (live on Base mainnet + Sepolia) rather than a new contract:
obol skills calldata set-hash → setMetadata(agentId, "skill.sha256:<name>@<ver>", <hash>) on the IdentityRegistry — binds bundle bytes to the publisher identity.
obol skills calldata feedback → giveFeedback with tag1="asr:skill", tag2="eip155:<chainId>:<registry>:<agentId>:<name>@<ver>" — per-skill ratings under the publisher's agentId, on-chain filterable via getSummary(agentId, raters, tag1, tag2). The tag convention follows the draft ERC-8239 (ethereum/ERCs PR #1704) so we are forward-compatible if it merges; we deliberately do NOT depend on its contracts (unmerged, Sepolia-only).
obol skills reputation (summary read w/ --raters whitelist → spam-resistant) and obol skills verify (local bundle sha256 vs on-chain metadata).
All chain writes are operator-submitted calldata. The controller never signs.
Why
The 402 response advertises extra.skill = {name, version, sha256}for free, pre-purchase — a buyer can verify what they will get against the publisher's on-chain hash before paying, and verify the bytes after. That closes the marketplace loop (discover → verify → pay → re-verify → rate) with only the registries already deployed.
Agent self-publish (and its guardrails)
A running agent can sell its own skills: a new namespace-scoped hermes-skill-publish Role grants ConfigMap create/get/update/patch in the agent's own namespace (it already had ServiceOffer CRUD). Two containment layers:
A new ValidatingAdmissionPolicy rule: agent ConfigMap writes MUST match *-skill-bundle — hermes-config and every other operator-managed ConfigMap are untouchable (test-pinned).
The controller refuses skill offers whose upstream isn't the controller-rendered bundle workload (anti-spoof: the advertised hash can never describe someone else's upstream).
Bundle ConfigMap applied server-side (client-side apply would blow the last-applied annotation cap for bundles >~190 KB).
Bundle workload names capped at the 63-char Service/label limit with hash fallback.
obol sell delete cleans up the bundle ConfigMap (CLI-created, so no ownerRef GC).
Offers persist in the sell resume ledger → survive host reboots via obol sell resume / stack up.
This PR also carries internal/erc8004/{reputation,validation}.go (calldata builders + readers for the Reputation/Validation registries) which the CLI commands need — additive, golden-tested selectors.
Validation
Full unit suite green (controller render/reconcile, verifier 402 extras, CLI flags, golden calldata, CRD↔Go parity, deterministic-pack tests).
Live smoke on a fresh k3d cluster (dev-built images from this branch): sell → condition ladder green → 402 extra.skill byte-exact vs served bundle → VAP denies the agent SA on hermes-config and allows *-skill-bundle → delete cleans everything.
Paid end-to-end on Base Sepolia through the public facilitator: agent-signed one-shot x402 payment → HTTP 200, settlement tx 0xb3075516fbbb4c14076b5b94d7db30e2a68ae2c2cf977c58ba1e8ca0715da6d3 (status 0x1), exact ±0.001 USDC balance deltas on buyer and payTo.
New flows/flow-19-skill-sale.sh + docs/guides/skill-marketplace.md.
Known v0 limitations
Re-publishing a bundle serves stale bytes for the ConfigMap propagation window (~60–120 s); the content-hash pod annotation rolls the server on reconcile.
buy.py pay is text-only — the printed purchase instructions steer binary downloads to a binary-safe client (paid skill.json fetch is the documented buy.py path).
Per-copy licensing is off-chain; the on-chain layer covers identity, integrity, and reputation.
It's not. It sells the bundle bytes with integrity + a publisher-portable identity, vs. sell mcp which proxies a running tool.
Basically selling atomic skill(s) that are being used by a given agent.
sell mcp sells RUNTIME: you host a tool, the buyer calls it per-request,
your API key stays server-side, the buyer never possesses the tool. Renting
an API.
sell skill (share mode) sells the ARTIFACT: the buyer pays once, downloads
the SKILL.md + scripts bundle, and runs it inside their own agent forever.
Buying the package, not the API. The bytes are sha256-pinned to the seller's
on-chain identity, so the buyer verifies integrity before and after paying.
sell skill --as-service is the only bit that overlaps sell agent — it's
sugar over the agent path for selling a skill's execution. You're right that
part is thin; it's there for completeness.
The user: a seller whose edge isn't GPU but a capability — a good research
skill, a trading workflow, a domain tool. Our whole sell surface today is
inference-by-the-token, which is a commodity: every seller offers the same open
models and competes on price to the floor. Skills are the differentiated,
higher-margin inventory — package your expertise once, sell it portable to
other agents. It moves a seller from "rent my hardware" to "buy my know-how,"
and it's the missing distribution channel for the ~21 skills we already ship
plus anything third parties write (today there's no integrity-preserving way to
hand a skill to another agent).
The --as-service mode was thin sugar over `obol sell agent` (it emitted a
plain type=agent offer with the skill name in registration metadata, no
controller involvement). It duplicated the agent sell path and muddied the
`sell skill` surface, which is about selling bundle BYTES. Removed the flag,
its --agent companion, the runSellSkillAsService/buildSkillServiceOfferManifest
code, and the service-mode test; docs now point at `obol sell agent` for
selling a skill's execution. SHARE mode (paid bundle download) is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Makes a skill (a
SKILL.md+ scripts bundle, like the ones embedded in the obol binary) a first-class sellable and ratable unit on the stack, in two modes:ServiceOffer type=skill: the gzipped bundle lives in a ConfigMap, the controller validates it (existence, 900 KB cap, sha256 match) and renders a restricted-PSS busybox httpd servingbundle.tar.gz+skill.jsonbehind the standard x402 payment gate at/services/<name>/*.obol sell skill --as-service --agent <a>is thin sugar over the existingtype=agentoffer path, carrying the skill identity in registration metadata. Zero new controller surface.Ratings and integrity ride ERC-8004 (live on Base mainnet + Sepolia) rather than a new contract:
obol skills calldata set-hash→setMetadata(agentId, "skill.sha256:<name>@<ver>", <hash>)on the IdentityRegistry — binds bundle bytes to the publisher identity.obol skills calldata feedback→giveFeedbackwithtag1="asr:skill",tag2="eip155:<chainId>:<registry>:<agentId>:<name>@<ver>"— per-skill ratings under the publisher's agentId, on-chain filterable viagetSummary(agentId, raters, tag1, tag2). The tag convention follows the draft ERC-8239 (ethereum/ERCs PR #1704) so we are forward-compatible if it merges; we deliberately do NOT depend on its contracts (unmerged, Sepolia-only).obol skills reputation(summary read w/--raterswhitelist → spam-resistant) andobol skills verify(local bundle sha256 vs on-chain metadata).All chain writes are operator-submitted calldata. The controller never signs.
Why
The 402 response advertises
extra.skill = {name, version, sha256}for free, pre-purchase — a buyer can verify what they will get against the publisher's on-chain hash before paying, and verify the bytes after. That closes the marketplace loop (discover → verify → pay → re-verify → rate) with only the registries already deployed.Agent self-publish (and its guardrails)
A running agent can sell its own skills: a new namespace-scoped
hermes-skill-publishRole grants ConfigMap create/get/update/patch in the agent's own namespace (it already had ServiceOffer CRUD). Two containment layers:*-skill-bundle—hermes-configand every other operator-managed ConfigMap are untouchable (test-pinned).Notable implementation details
internal/skillpkg): sorted entries, fixed epoch mtimes, cleared uid/gid, normalized modes → reproducible sha256 across machines (test-pinned). Warn-only secret scan before publish.obol sell deletecleans up the bundle ConfigMap (CLI-created, so no ownerRef GC).obol sell resume/stack up.internal/erc8004/{reputation,validation}.go(calldata builders + readers for the Reputation/Validation registries) which the CLI commands need — additive, golden-tested selectors.Validation
extra.skillbyte-exact vs served bundle → VAP denies the agent SA onhermes-configand allows*-skill-bundle→ delete cleans everything.0xb3075516fbbb4c14076b5b94d7db30e2a68ae2c2cf977c58ba1e8ca0715da6d3(status 0x1), exact ±0.001 USDC balance deltas on buyer and payTo.flows/flow-19-skill-sale.sh+docs/guides/skill-marketplace.md.Known v0 limitations
buy.py payis text-only — the printed purchase instructions steer binary downloads to a binary-safe client (paidskill.jsonfetch is the documented buy.py path).