The Obol Stack turns a laptop or home server into a self-sovereign AI agent business:
- Run an agent locally. A Hermes agent with its own crypto wallet, backed by your local models (Ollama) or any cloud provider, orchestrated in a local Kubernetes cluster.
- Sell to buyers worldwide. Put inference, agents, or any HTTP service up for sale behind x402 micropayments (USDC or OBOL). Buyers pay per request; you get paid onchain, directly to your wallet — no platform in between.
- Get discovered. A Cloudflare tunnel gives you a public URL serving a storefront, a machine-readable service catalog, and optional onchain ERC-8004 agent registration.
- Buy from other sellers. Purchase paid inference from any x402 seller and route it to your agents.
- Own your chain access. Sync blockchain networks (Ethereum, Aztec) locally instead of trusting third-party RPCs.
Built on Kubernetes with Helm for package management. Read more in the docs.
Important
The Obol Stack is alpha software. If you encounter an issue, please open a GitHub issue.
Docker must be installed and running:
- Linux: Docker Engine installation guide
- macOS/Windows: Docker Desktop
For local models, install Ollama and pull at least one chat-capable model (e.g. ollama pull qwen3.5:4b). The installer may offer to install Ollama; if you decline and do not configure a cloud model, obol stack up skips the default Hermes agent until you run obol model setup and then obol agent init. Prefer a cloud provider anytime with obol model setup (see Models).
curl -fsSL https://stack.obol.org | bashPin a release (use the current tag from the releases page, not an ancient example):
curl -fsSL https://stack.obol.org/v0.15.0 | bashThe installer sets up the obol CLI and all dependencies (kubectl, helm, k3d, helmfile, k9s) into ~/.local/bin/, verifies release checksums, configures your PATH, tries to add obol.stack to /etc/hosts, and offers to start the cluster.
If /etc/hosts cannot be updated (no sudo / you cancel), the install still finishes — add the host, then start the stack yourself:
echo "127.0.0.1 obol.stack" | sudo tee -a /etc/hosts
# After stack up, agent hostnames are also managed (obol-agent.obol.stack, …)
obol stack init
obol stack up
obol agent init # if the default agent was skipped (no model yet)Non-interactive / CI: set OBOL_NONINTERACTIVE=true so hosts updates do not prompt for a sudo password (they fail fast if credentials are not already cached). Combine with a pre-written /etc/hosts entry or run sudo -v first.
Verify:
obol version# Start the stack
obol stack init
obol stack up
# Apply agent capabilities to the default stack-managed agent
obol agent init
# Inspect the default Hermes agent and grab its dashboard token
obol agent list
obol agent auth obol-agentobol stack up provisions the cluster, auto-detects host Ollama models into the LiteLLM gateway (when present), and deploys the default Hermes agent with its own wallet behind a remote signer. The Cloudflare tunnel stays dormant until the first sell workflow (or obol tunnel restart / obol tunnel setup).
Open the frontend at:
http://obol.stack:8080
Use obol.stack, not localhost. Traefik routes the frontend (and eRPC) only for Host: obol.stack. http://localhost:8080 returns 404 even when the stack is healthy.
- Prefer
:8080on macOS when port 80 is unavailable (or after editingk3d.yamlto drop privileged 80/443 binds). - If port 80 is mapped,
http://obol.stack/works too.
Hermes dashboard (root edge-redirects to the password form):
http://obol-agent.obol.stack
(or with :8080 when that is your ingress)
- Username:
obol - Password: the agent API token from
obol agent auth obol-agent
Details: Hermes dashboard login.
The core loop: put a service on sale → get a public URL → get registered → buyers pay per request, settled onchain to your wallet.
# Sell local Ollama inference, priced per request (USDC on Base by default)
obol sell inference my-qwen --model qwen3:8b --price 0.001 --pay-to 0x...
# Or price per million tokens, or accept OBOL instead of USDC
obol sell inference my-qwen --model qwen3:8b --per-mtok 0.50 --token OBOL --pay-to 0x...If you omit --pay-to, the agent's own wallet address is auto-detected from the remote signer — your agent earns for itself. Set defaults once with obol sell pricing --pay-to 0x... --chain base.
Check it's live:
obol sell list
obol sell status my-qwen
obol sell info # buyer's-eye view of everything on saleA tunnel gives buyers a permanent URL to reach you. Create a tunnel in the Cloudflare dashboard (Networks → Tunnels), route its Public Hostname to http://traefik.traefik.svc.cluster.local:80, then paste the connector token (you can paste the whole cloudflared tunnel run --token … line):
obol tunnel setup --hostname stack.example.com <connector-token>
obol tunnel statusThis uses a least-privilege, single-tunnel connector token — no account-wide API key required. Need a domain? Buy or transfer one in the Cloudflare dashboard so it is a zone in your account.
Your public hostname now serves a full discovery surface for buyers, humans and agents alike:
| Path | What buyers get |
|---|---|
/ |
Storefront landing page with your branding |
/skill.md |
Machine-readable service catalog with worked x402 payment examples |
/api/services.json |
JSON catalog: pricing, models, payment requirements |
/openapi.json |
OpenAPI spec for your paid endpoints (indexed by x402 scanners) |
/.well-known/agent-registration.json |
ERC-8004 agent registration document |
/services/<name>/* |
The paid services themselves (402 challenge → pay → response) |
Brand your storefront — name, logo, theme, and copy apply to every buyer-facing surface (storefront, 402 paywall pages, sign-in, API docs, per-offer landing pages) — and optionally register your agent identity onchain:
obol sell info set \
--display-name "One Dollar Audit" \
--tagline "A serious security audit. One dollar." \
--logo-file ./logo.png \
--theme obol \
--description 'Every audit ships as a **signed report** — findings ranked by severity.'
obol sell register --chain base # publish ERC-8004 registration
obol sell identity # inspect your onchain identity| Default storefront | Branded seller |
|---|---|
![]() |
![]() |
Three theme presets ship built in — light (default), dark, and obol — plus
an --accent '#hex' override. Descriptions accept a safe markdown subset.
Buyers hitting a paid route in a browser get a checkout-style 402 page in the
same identity:
| Default 402 page | Branded 402 page |
|---|---|
![]() |
![]() |
Offers bound to their own hostname can override the identity per origin
(obol sell info set --hostname audit.acme.io --display-name AuditCo), and
--css-file injects a custom stylesheet targeting the stable data-obol
hooks on every page for full control short of bringing your own frontend.
For the full end-to-end walkthrough, see docs/guides/monetize-inference.md.
Anything that speaks HTTP can be payment-gated:
# Gate any in-cluster HTTP service (here: Ollama's raw API in the llm namespace)
obol sell http ollama-gated \
--upstream ollama --port 11434 --namespace llm --health-path /api/tags \
--per-request 0.001 --chain base --pay-to 0x...
# Sell access to an agent itself (wraps an Agent created with `obol agent new`)
obol sell agent my-researcher --per-request 0.01 --pay-to 0x...
# Run an x402-paid MCP server that proxies a backend API with your own key injected
obol sell mcp my-toolNote
--namespace sets both the offer's namespace and the upstream service's namespace. Pass the same -n <namespace> to follow-up commands (sell status, sell stop, sell delete) — the CLI prints the right invocation after creation.
obol sell list # everything on sale
obol sell status <name> # operator health and conditions
obol sell update <name> --price 0.002 # change price or payout wallet in place
obol sell stop <name> # take an offer off sale (keeps it)
obol sell delete <name> # remove an offer
obol sell resume # replay all offers after a host rebootobol stack up re-publishes your offers automatically after a restart; obol sell resume --install-boot-unit adds a systemd user unit on Linux so offers come back on boot.
Back up your business. Wallets, agent memory, and offers live only on this machine:
obol stack export # full backup archive (wallets, brains, offers, config)
obol stack import <archive> # restore onto a fresh stack
obol agent wallet backup # wallet-only encrypted backupBuy paid inference from any x402 seller and route it to your agents:
# Walk a seller's catalog, preview cost, pre-sign payments, wire up the model
obol buy inference https://inference.example.com/
# Pay from a specific agent's wallet and switch that agent onto the paid model
obol buy inference https://inference.example.com/ --agent research
# Promote the purchased model to the stack-wide default
obol buy inference https://inference.example.com/ --set-defaultThe CLI probes the seller's 402 pricing, prompts for how many requests to pre-authorize (with a cost preview), signs payment authorizations via your agent's remote signer, and publishes the model as paid/<model> through the LiteLLM gateway. Agents can also buy autonomously — the embedded buy-x402 skill gives them probe, buy, pay, balance, and auto-refill tooling.
Hermes is the default runtime, deployed by the stack as obol-agent. Multiple instances run side-by-side, each in its own namespace with its own wallet.
OpenClaw was removed in v0.16. If you still run an OpenClaw instance,
obol stack uplists it with its keystore and password paths: copy those before deleting the namespace. To move the wallet into Hermes, back it up with obol v0.15 (obol agent wallet backup --runtime openclaw <id> --file w.json), then runobol agent wallet restore --input w.json --force(this replaces the Hermes agent's wallet, so back that up first).
# Default stack-managed Hermes agent
obol agent list
obol agent auth obol-agent
obol hermes skills list
# Declare a new sub-agent with a model, skills, an objective, and its own wallet
obol agent new research --model qwen3:8b --skills ethereum-networks,buy-x402 \
--objective "Research onchain data and sell reports" --create-wallet
# Wallet management
obol agent wallet address
obol agent wallet backupUse obol agent for Obol-managed lifecycle and auth flows. Use obol hermes for native Hermes CLI commands against the default instance, or pass --agent <id> for a non-default instance. An agent created with agent new can itself be put on sale with obol sell agent <name>.
The stack ships with embedded Obol skills installed automatically for the default Hermes agent and its sub-agents. Skills give agents domain-specific capabilities — from querying blockchains to buying and selling services.
| Skill | Purpose |
|---|---|
sub-agent-business |
The business playbook — design, evaluate, price, and sell specialised sub-agents people pay per turn |
agent-factory |
Spawn durable child agents with their own namespace, wallet, skills, and paid endpoint |
sell |
ServiceOffer CRUD — payment-gated routes, reconciliation status, ERC-8004 registration |
monetize-guide |
Guided end-to-end walkthrough for selling inference or an HTTP API |
buy-x402 |
Buy paid services: probe pricing, pre-sign payments, auto-refill, check balances |
discovery |
Find agents registered on the ERC-8004 Identity Registry across chains |
swap |
Treasury moves — swap USDC/ETH/OBOL on Base and mainnet via Uniswap V3 |
| Skill | Purpose |
|---|---|
ethereum-networks |
Read-only Ethereum queries via cast — blocks, balances, contract reads, ERC-20, ENS |
ethereum-local-wallet |
Sign and send Ethereum transactions via the per-agent remote-signer |
addresses |
Verified contract addresses — payment rails, DeFi, tokens, bridges, ERC-8004 registries |
building-blocks |
DeFi legos and protocol composability — Uniswap, Aave, Aerodrome, Pendle |
concepts |
Mental model — state machines, incentive design, why nothing onchain is automatic |
gas |
Real transaction costs today, mainnet vs L2, fee settings |
indexing |
The Graph, Dune, Ponder, event-first design for onchain data at scale |
l2s |
L2 comparison — Base, Arbitrum, Optimism, zkSync with costs and use cases |
standards |
ERC-8004, x402, EIP-3009, EIP-7702, ERC-4337 — spec details and integration patterns |
wallets |
Wallet management — EOAs, Safe multisig, EIP-7702, key safety for AI agents |
why |
Why Ethereum — the AI agent angle with ERC-8004 and x402 |
| Skill | Purpose |
|---|---|
obol-stack |
Kubernetes cluster diagnostics — pods, logs, events, deployments |
distributed-validators |
Obol DVT cluster monitoring, operator audit, exit coordination |
Manage skills at runtime:
obol hermes skills list # native Hermes skills CLI (default agent)
obol agent sync # re-render the agent and re-inject embedded Obol skillsSkills are delivered via host-path PVC injection — no ConfigMap size limits, works before pod readiness, and survives pod restarts.
The stack runs LiteLLM as an in-cluster OpenAI-compatible gateway that proxies all LLM traffic. By default, host Ollama models are auto-detected on obol stack up.
To use a cloud provider instead (or as well):
# Interactive — walks you through provider pick, key creation, and free-tier models
obol model setup
# Or scriptable
obol model setup --provider openrouter --api-key sk-or-...
obol model setup --provider anthropic --api-key sk-ant-...
# Any OpenAI-compatible endpoint (vLLM, sglang, a remote GPU box)
obol model setup custom --endpoint http://192.168.1.20:8000/v1 --model my-model
# Manage the roster
obol model list # what's routed, in priority order
obol model prefer <id> # promote a model to the default slot
obol model status # provider stateMinimum local model size: agents rely heavily on tool calling. Models below ~7B parameters tend to ignore the structured tool-calling channel or hallucinate tool failures. Recommended local minimums for reliable agent behaviour: llama3.1:8b, qwen3:8b, or qwen2.5:7b (instruct). The 1B–4B and *-coder variants remain fine for embeddings or single-turn completions sold via obol sell inference.
Install and run blockchain networks as isolated deployments. Each installation gets a unique namespace so you can run multiple instances side-by-side. Local nodes are automatically registered as priority upstreams for the stack's RPC gateway.
# Installed deployments (+ installable types and remote RPCs)
obol network list
# Install a network (defaults to network name as ID)
obol network install ethereum
# → ethereum/mainnet
# Deploy to the cluster (auto-selects if only one deployment exists)
obol network sync
# Or by full identifier, or all at once
obol network sync ethereum/mainnet
obol network sync --all
# Sync progress: EL + CL state and a one-line verdict per node
obol network status
obol network status ethereum/mainnet -o json
# Add a remote RPC instead of running a node
obol network addAvailable networks: ethereum, aztec
Ethereum options: --network (mainnet, sepolia, hoodi), --execution-client (reth, geth, nethermind, besu, erigon), --consensus-client (lighthouse, prysm, teku, nimbus, lodestar, grandine), --mode (full, archive), --since (partial archive: merge, 365d, a block number)
# Hoodi node with a specific client pair
obol network install ethereum --network=hoodi --execution-client=geth --consensus-client=teku
obol network sync ethereum/hoodi
# Delete a deployment
obol network delete ethereum/mainnet --forceTip
Use obol network install <network> --help to see all options.
Install arbitrary Helm charts as managed applications — useful for running upstreams you then put on sale with obol sell http:
# Install from ArtifactHub
obol app install bitnami/redis
# With specific version
obol app install bitnami/postgresql@15.0.0
# Customize values at install or sync time (persisted into the app's values.yaml)
obol app install bitnami/redis --set architecture=standalone --set auth.enabled=false
obol app sync redis --values ./my-overrides.yaml --set image.tag=7.2
# Deploy to cluster (auto-selects if only one app is installed)
obol app sync
obol app sync postgresql/eager-fox
# List and manage
obol app list
obol app delete postgresql/eager-fox --forceInstalled apps are re-synced automatically on obol stack up, so they survive cluster recreation. After a sync, the CLI prints a ready-to-run obol sell http command for each service the app exposes.
Find charts at Artifact Hub.
obol stack up # Start the cluster (replays models, RPCs, agents, offers)
obol stack down # Stop the cluster (preserves data)
obol stack purge -f # Remove everything (offers a full export first)
obol update # Check for CLI and chart updates
obol upgrade # Apply chart upgrades
obol k9s # Interactive cluster UIThe obol CLI wraps kubectl, helm, helmfile, and k9s pointed at the stack's kubeconfig — an exported KUBECONFIG in your shell is ignored; only an explicit --kubeconfig argument overrides it. Arguments go to the tool unchanged, so put tool flags after the tool name:
obol kubectl get pods --all-namespaces -o wide
obol helm list --all-namespacesTo use the plain tools (with their own completion and plugins such as krew) against the stack, load the stack environment into your shell:
eval "$(obol env)" # bash/zsh; fish: obol env --shell fish | source
kubectl get pods -A
eval "$(obol env --unset)" # undoFor direnv, add eval "$(obol env --shell bash)" to .envrc.
Edit ~/.config/obol/k3d.yaml, remove the 80:80 and 443:443 port entries (keep 8080:80 and 8443:443), then restart:
obol stack down && obol stack upAccess at http://obol.stack:8080 instead (still with the obol.stack host — not localhost).
obol stack up also tries to refresh managed hostnames (obol.stack, obol-agent.obol.stack, …). A failed hosts write is a warning, not a hard stop — the cluster still comes up. Fix hosts, then re-run obol stack up or obol agent sync so agent hostnames are registered.
# Minimal manual entry
echo "127.0.0.1 obol.stack" | sudo tee -a /etc/hosts
# Skip interactive sudo during automation (must already have NOPASSWD or a cached timestamp)
OBOL_NONINTERACTIVE=true obol stack upIf sell/buy flows misbehave, verify in order:
# 1) Kubeconfig matches the currently running k3d cluster (ports can drift).
k3d kubeconfig write <cluster-name> -o ~/.config/obol/kubeconfig.yaml --overwrite
# 2) Stack components are healthy.
obol kubectl get pods -A
# 3) Seller route exists and is Ready.
obol sell list
obol sell status <offer-name> -n <namespace>
# 4) Buyer wallet and balances are available.
obol kubectl exec -n hermes-obol-agent deploy/hermes -c hermes -- \
python3 /data/.hermes/obol-skills/buy-x402/scripts/buy.py balanceRaw direct X-PAYMENT requests through the Traefik ForwardAuth route are not a supported production payment path. The verifier is intentionally verifyOnly: true, so Traefik can gate requests but is not the final settlement point. Use x402-buyer for cluster-routed paid traffic, or obol sell inference for direct buyers that need to send raw X-PAYMENT.
If you call x402-verifier /verify directly for debugging, you must send X-Forwarded-Uri (and usually X-Forwarded-Host) like Traefik does, or the verifier correctly returns 403 forbidden: missing forwarded URI.
PurchaseRequest.status(remaining/spentandconditions[].message) is a reconciled snapshot, not a live per-request counter. For real-time auth pool state, usex402-buyerGET /statusfrom the litellm pod.- Agent-managed refill is driven by
buy.py process --all; use live sidecar status as the source of truth for refill decisions.
Follows the XDG Base Directory specification:
| Directory | Purpose |
|---|---|
~/.config/obol/ |
Cluster config, kubeconfig, network and app deployments |
~/.local/share/obol/ |
Persistent volumes (blockchain data, agent state) |
~/.local/bin/ |
CLI binary and dependencies |
curl -fsSL https://stack.obol.org | bashThe installer detects your existing installation and upgrades safely.
obol stack purge -f
rm -f ~/.local/bin/{obol,kubectl,helm,k3d,helmfile,k9s,obolup.sh}
rm -rf ~/.config/obol ~/.local/share/obolgit clone https://github.com/ObolNetwork/obol-stack.git
cd obol-stack
OBOL_DEVELOPMENT=true ./obolup.shDevelopment mode uses .workspace/ instead of XDG directories and runs go run on every obol invocation — no build step needed.
Already have a stack in ~/.config/obol? Copy .envrc.local.example → .envrc.local and source it so dev commands use that cluster (avoids a second k3d stack in .workspace/config). Frontend in-cluster: FRONTEND_DIR=../obol-stack-front-end just dev-frontend-rebuild → http://obol.stack:8080 (see CLAUDE.md → Local frontend development).
Networks are embedded at internal/embed/networks/. Each uses annotated Go templates that auto-generate CLI flags:
# @enum mainnet,hoodi
# @default mainnet
# @description Blockchain network to deploy
network: {{.Network}}See CONTRIBUTING.md for details.





