v0.10.0 — Agents that earn
v0.10.0 — Agents that earn
Sellers know more than buyers about their products. This is true for agents too. This release allows stack users to sell specialised agents alongside their x402 APIs.
v0.10.0 is the release where Obol agents become economic actors. They sell services over x402 micropayments — raw inference, whole agents, gated HTTP APIs, and MCP tool calls.
Get started selling services from your stack with obol sell demo to sell a basic hello-world service, and if you have a capable model setup (locally or remotely, use obol model setup), run obol sell demo quant to sell a basic Obol Agent that can answer on-chain queries. Tag @Obol_Collective on X with your storefront URL and maybe we'll check it out. 👀
Once the demos work, your next step is to build your own agent businesses. What alpha will you create, package, and sell to the growing agentic economy? A Polymarket sharp, a Bankr Bot analyst, a Uniswap Unicorn, an expert on all things Base, or your favourite DeFi app? You show us. Read more about selling services in our docs, and send your feedback and feature wishlist here.
Note
Base Sepolia ETH faucet · Base Sepolia USDC faucet. This release also wires a Base Sepolia OBOL faucet for testing OBOL-priced offers.
Important
Upgrading an existing stack? Pre-existing clusters must be recreated — this release line changed how cluster volumes are owned. See Breaking changes / Migration notes before running obol stack up with the new CLI.
Warning
This software is early alpha, you could lose what you put in. Please use caution when it comes to non-testnet assets.
Install / Upgrade
# Install this release
OBOL_RELEASE=v0.10.0 bash <(curl -s https://stack.obol.org)
# Run the stack
obol stack init && obol stack up
# Sell something
obol sell demo
# Setup a remote model unless your local one is fast enough
obol model setup
# Now sell a demo agent that leverages that model
obol sell demo quant
# Chat with your agent, (maybe tell it to buy one of its services to see it work)
obol hermes chat
# Next hand over to your Claude, install the skills, and make an agent business of your own
claude
/plugin marketplace add ObolNetwork/skills
/plugin install obol@obol
"Help me sell a service on the Obol Stack that agents will pay for."Release Highlights
Agents selling to agents — the full commerce loop
The buy and sell sides both landed. A stack can publish a paid service and another stack can pay for it, end to end:
# Seller — gate any model, agent, HTTP API, or MCP tool behind x402
obol sell inference my-model --per-mtok 0.50 --chain base-sepolia --pay-to 0x...
obol sell http my-api --upstream svc --port 8080 --per-request 0.001 --pay-to 0x...
obol sell agent quant --price 0.001 --chain base-sepolia # sell a whole agent
obol sell mcp weather --price 0.001 ... # sell one tool, key stays server-side
# Buyer — discover, pay, and spend from inside an agent
buy.py probe <seller-url>
buy.py pay-agent <seller-url> --model <id> --message 'summarize the docs' # streaming, one-shot
obol buy inference <seller-url> [--token USDC|OBOL] [--set-default] # wires paid/<model> via a sidecar poolPayment is USDC (EIP-3009) on Base or mainnet, or OBOL (Permit2) on mainnet.
Agent namespace isolation — your agent's keys and API, sandboxed
Every agent business (obol agent new / obol sell agent) runs behind an agent-isolation NetworkPolicy with an "internet-open, cluster-closed" shape. Each agent business is a sealed tenant:
- Agent A cannot reach Agent B — not its Hermes API, and crucially not its remote-signer, the process that holds the wallet key. Cross-agent traffic is denied by default.
- Paid traffic reaches only the agent's API, never the signer. The endpoint that takes money is exposed through the tunnel; the endpoint that holds keys isn't reachable from outside the namespace at all.
- Egress is allowlisted to exactly what an agent needs — DNS, LiteLLM, chain RPC via eRPC, Traefik, and the public internet for skills/facilitators — while the cloud instance-metadata endpoint (
169.254.169.254) is blocked, so semi-untrusted skill code can't SSRF a node's IAM credentials. - Defense in depth: a per-agent remote-signer bearer token is provisioned alongside the policy.
An operator can now run a dozen agents — each with its own wallet, skills, and customers — and know a compromise of one won't drain or impersonate another. Future versions will grant more fine grained LLM spend management for your agent businesses.
Paid MCP tools without exposing your API key — obol sell mcp
Any credentialed HTTP service can be resold to agents per call as a paid MCP tool. The buyer's tool arguments are forwarded to your backend with your API key injected server-side — the credential is never sent to buyers. Payment rides in-band in the MCP request's _meta, and the wrapper runs verify → execute → settle inside the tool call, so a caller is never charged for a failed tool.
Discover, register, and front your storefront
Offers publish discovery metadata the rest of the network can find: a /skill.md catalog, an /api/services.json feed, and an ERC-8004 on-chain registration (obol sell register) served from /.well-known/agent-registration.json. A Next.js storefront landing page fronts the tunnel hostname with clickable service endpoints, and obol tunnel setup is now a real wizard for binding a persistent hostname. Let us know how these storefronts can be more compelling and user/agent-friendly.
Smaller wins
pay-agentstreaming — agents re-emit a remote agent's reply token-by-token; long replies keep tunnels alive instead of timing out on a buffered body.- Per-offer payment clock —
--max-timeout(up to 24h) flows into the 402, so long-running paid work no longer has to fit in a 60s window. - Path-conflict protection — two offers can no longer silently shadow each other on the verifier's route table; first-claimant-wins is explicit, and the CLI fails fast before anything is created.
- Reboot & recreation resilience —
obol sell resume(andobol stack up) replay every persisted offer;obol stack export/obol stack importcapture a whole stack — agents, wallets, config, and offers — into one archive. - Model ergonomics — a freshly configured model auto-promotes to the agents' primary;
obol model preferpins ordering. - HA-safe controller — client-go leader election so the serviceoffer-controller can scale without double-reconciling.
- Friendlier ops — disk-pressure handling, and
obol stack down/purgenow confirm when services are actively serving traffic.
Security hardening
- Agent namespace isolation (see Highlights) — cross-agent and signer access denied by default; IMDS egress blocked; per-agent signer bearer auth.
- Controller Secret RBAC scoped to named secrets — the serviceoffer-controller can no longer enumerate arbitrary Secrets; cross-namespace wallet reads are denied, and
ca-certificates/x402-buyer-adminwere dropped from the agent allow-list. - Cross-namespace
spec.agent.refrejected — an offer can't point at an Agent in another namespace to borrow its identity. - Restricted Pod Security Standard across embedded workloads — non-root, no privilege escalation, dropped capabilities.
- Hardened
obol stack import— symlink-target escapes and decompression bombs are rejected, so importing an untrusted archive can't write outside the extraction root or fill the disk.
CLI changes
New commands
obol sell agent— wrap an Agent CR in atype=agentServiceOffer (sell a whole agent).obol sell resume— replay every persisted offer after a host reboot (--install-boot-uniton Linux).obol sell pricing | register | identity | info— quote prices, publish ERC-8004 registration, manage identity, print buyer instructions.obol stack export/obol stack import— back up and restore a full stack (agents, wallets, config, offers).obol sell mcp— run an x402-paid MCP tool server (forwards to a backend, injects your key server-side).obol agent new(aliasonboard) — declare a CRD-backed sub-agent via--model,--skills,--objective,--create-wallet.obol model prefer— pin one or more models to the head of the agents' model list.
Changed flags / behavior
obol buy inference [<seller-url>]— seller URL is now positional; auto-resolves model + token from the catalog, supports--token OBOL,--set-default,--cost-cap, and opt-in identity verification via--expected-agent-id.obol model setup— a freshly configured model auto-promotes to the agents' primary (no separatepreferstep needed for the common case).obol stack down/obol stack purge— prompt for confirmation when offers are actively serving traffic;purge --forcenow offers a full stack export first.obol sell http --max-timeout— payment window is configurable per offer (default 300s, up to 24h).
Renamed / removed / deprecated
hermes token→obol agent auth(aliastoken) — token retrieval moved onto the agent command.--wallet→--pay-toonobol sell *—--walletremains as a deprecated alias.
Breaking changes / Migration notes
-
Volume ownership changed (recreate required). This release line replaced the volume-permission patchwork with kubelet-owned, non-root volumes everywhere. Clusters created on earlier builds keep host-path-typed PVs that the new non-root pods (UID 1000, no chown init) cannot read. Back up wallets, then recreate the cluster:
obol agent wallet backup # + any per-agent wallets you care about obol stack down obol stack purge --force obol stack init obol stack up -
Pre-release tester warning. If you ran an unreleased marketplace or chart-consolidation branch,
obol stack upmay fail with Helminvalid ownership metadataerrors for resources that moved into thebasechart. This is not a supported migration path — recreate the stack as above.
Known issues
- ERC-8004 registrations are bound to the tunnel hostname — re-run
obol sell registerif the hostname changes. Consider setting up a permanent tunnel URL.
What's Changed
- fix(defaults): resolve host gateway via Docker for Colima/Rancher Desktop by @apham0001 in #432
- feat: add Base Sepolia OBOL faucet contracts by @bussyjd in #443
- feat: wire Base Sepolia OBOL faucet env by @bussyjd in #447
- fix: lower Base Sepolia OBOL faucet default amount by @bussyjd in #448
- fix: hermes PVC ownership on Linux k3d + bootstrap ingress URL by @nickh-obol in #446
- chore(frontend): bump frontend image to v0.1.21-rc1 by @bussyjd in #449
- integration: validate tunnel onboarding with live OBOL faucet flow by @bussyjd in #452
- Add release description template by @bussyjd in #456
- feat(tunnel): make remote setup a real wizard by @bussyjd in #457
- chore: bump frontend to v0.1.23 and hermes-agent to v2026.5.7 by @bussyjd in #461
- feat(storefront): make service endpoint clickable by @bussyjd in #462
- fix(serviceoffer-controller): harden agent reconciliation and storefront by @bussyjd in #463
- feat(stack): selective image rebuild, Claude plugin tip, demo agent model pin by @bussyjd in #464
- fix(serviceoffer-controller): align remote-signer config with v0.3.0 image by @bussyjd in #465
- ci(renovate): add scheduled Renovate workflow by @bussyjd in #460
- chore(docker): bump image tags by @OisinKyne in #467
- test(flow-08): tighten buy-side correctness assertions by @bussyjd in #466
- fix(tunnel): add --overwrite-dns to obol tunnel login/setup by @bussyjd in #471
- fix(sell): accept --yes / -y as aliases for --force on sell delete by @bussyjd in #472
- fix(x402): scope token-availability error to the requested chain by @bussyjd in #469
- fix(sell inference): three bugs surfaced by OBOL-priced run on Linux Docker by @bussyjd in #470
- release-smoke: green 13/13 (supersedes #476 #477 #478 #479 #483 #484) by @bussyjd in #490
- chore(buy-external): preserve cluster on FAIL, normalize obol-bin path, document CF-WAF UA by @bussyjd in #493
- chore: harden secret leak prevention by @aly-obol in #495
- post-490: fold #487 + #489, strip debug logs, drop SKIP_PULL (smoke 13/13) by @bussyjd in #492
- fix(tunnel): detect cloudflared zone-mismatch routing and fail loudly by @bussyjd in #473
- test(model): pin prefer + :Nb rank-parser behavior by @bussyjd in #474
- docs(CLAUDE.md): refresh model-ranking guidance to match current rank.go by @bussyjd in #480
- fix(hermes): host-side chown PVC backing dirs after sync (#475) by @bussyjd in #481
- chore(frontend): bump obol-stack-front-end v0.1.23 → v0.1.24 (digest-pinned) by @bussyjd in #482
- feat(flows): switch default QA LLM to qwen36-deep + 1-retry safety net for agent buy by @bussyjd in #496
- fix(buy): clearer hint when seller didn't publish on-chain identity by @bussyjd in #498
- fix(stack): warn loudly when no chat-capable LLM is reachable by @bussyjd in #499
- feat(buy): support OBOL-priced sellers via --token on obol buy inference by @bussyjd in #501
- fix(serviceoffer-controller): preserve operator-supplied description on inference offers by @bussyjd in #502
- fix(sell): allow concrete paid/ as default agent chat model by @bussyjd in #497
- fix(x402-buyer): set obol-buy-x402/1.0 User-Agent on outbound HTTP by @bussyjd in #503
- fix(x402-buyer): propagate upstream status/body and log every request by @bussyjd in #504
- docs: remove stale USDC-only sell wording by @peterxing in #508
- Clean up ui by @OisinKyne in #491
- chore(frontend): bump obol-stack-front-end v0.1.24 → v0.1.25-rc1 (digest-pinned) by @bussyjd in #505
- feat: add Hermes child agent factory and paid agent metadata by @bussyjd in #506
- Use native fsGroup for Hermes PVC ownership by @bussyjd in #514
- fix(hermes): host-side chown for CRD child agent PVCs on Linux k3d by @HananINouman in #511
- fix: resolve marketplace bundle architecture blockers by @bussyjd in #541
- feat: x402 marketplace + architecture review bundle (#513-#535) by @bussyjd in #536
- fix(cli): make cluster-running probe authoritative via kubectl, not file presence by @bussyjd in #537
- fix(x402): strip healthPath from buyer endpoint URL construction by @bussyjd in #539
- fix(stack): tolerate transient helm repo update failures, keep cluster running by @bussyjd in #538
- fix(stack): preload runtime images via k3s crictl by @bussyjd in #510
- feat(stack): confirm down/purge when services are serving traffic by @bussyjd in #512
- chore(model): remove inert --name flag from
obol model setup customby @bussyjd in #509 - fix(frontend): pin rc4 image and repair dependency automation by @bussyjd in #543
- fix: stabilize post-544 smoke train by @bussyjd in #551
- fix(model): retry inference probe on transient network errors by @bussyjd in #552
- chore(deps): bump front end to v0.1.25 by @OisinKyne in #553
- chore(deps): bump obol-stack-front-end to v0.1.26-rc1 by @bussyjd in #560
- Release v0.10.0-rc7 by @bussyjd in #565
- fix(x402): inject agent upstream auth + close cross-namespace agent.ref gap by @bussyjd in #566
- hotfix: fix frontend Hermes token RBAC by @bussyjd in #569
- [codex] bump Hermes image to v2026.5.28 by @bussyjd in #567
- Fix agent-backed service readiness reconciliation by @bussyjd in #572
- security(controller): scope serviceoffer-controller Secret RBAC to named secrets by @bussyjd in #570
- chore(deps): update cloudflare/cloudflared docker tag to v2026.5.2 by @github-actions[bot] in #574
- Limit frontend ServiceOffer RBAC by @bussyjd in #577
- Release v0.10.0-rc9 by @bussyjd in #578
- fix(hermes): reliable Hermes deploy on k3d (PVC ownership + RWO rollout) by @bussyjd in #580
- fix(rc9): GA blockers + monetize buy-side fixes from the v0.10.0-rc9 report by @bussyjd in #583
- Streamline sub-agents by @OisinKyne in #582
- chore(frontend): bump obol-stack-front-end image to v0.1.26 by @bussyjd in #585
- fix(perms): bulletproof local-path volume ownership across k3d / k3s / Linux by @bussyjd in #588
- feat(sell): explain ERC-8004 registration consequences at publish time by @bussyjd in #590
- fix(hermes): clear stale rollingUpdate so obol model sync reaches the agent by @bussyjd in #589
- fix(dev): bake WalletConnect project ID into frontend dev builds by @bussyjd in #591
- chore(dev): tag dev images :dev- instead of :latest (no cross-worktree poisoning) by @bussyjd in #587
- chore(controller): repin serviceoffer-controller to b39bcaa for rc11 by @bussyjd in #592
- release: v0.10.0-rc12 (consolidate #593/#594/#595/#597 + review hardening) by @bussyjd in #600
- security(agent-rbac): deny mother-agent cross-namespace wallet keystore reads by @bussyjd in #602
- fix(buy-x402): unify + extend x402 auth pool expiry (default 1 month, optional never) by @bussyjd in #601
- feat(buy-inference): positional URL, interactive prompts, default seller storefront by @OisinKyne in #607
- fix(agent): gate kubectl -t on both stdin and stdout being TTYs by @bussyjd in #611
- release: v0.10.0-rc14 (consolidate #609/#610/#614 + review hardening) by @bussyjd in #616
- chore: bump to latest docker tags by @OisinKyne in #620
- feat: import/export persistence clean up by @OisinKyne in #624
- fix(sell): tighten agent selling and sandboxing by @OisinKyne in #625
- feat(x402): bazaar discovery extension + x402scan-legible OpenAPI by @OisinKyne in #626
- chore: update images by @OisinKyne in #627
- fix: bugfix on rc16 by @OisinKyne in #628
- chore: update image pins by @OisinKyne in #629
New Contributors
- @aly-obol made their first contribution in #495
- @peterxing made their first contribution in #508
- @github-actions[bot] made their first contribution in #574
Full Changelog: v0.9.0...v0.10.0

