This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
What I Built
SlothPay โ the sloth that pays for you.
Machine-payable HTTP (the x402 flow, where a server answers 402 with a price and your software just... pays) is powerful and slightly terrifying: your software can spend money while you are not looking. The usual answers are a cloud dashboard, a closed trust API, or another subscription. SlothPay is the lazy, local answer.
You tell it once which resources your agents may buy and up to what price. Every night it:
- Fetches each resource in your want list.
- On a
402 Payment Required, it reads the seller's ATC/1.0 payment credential โ a signed, machine-checkable statement of who they are and what they charge. - Verifies it fail-closed: signature, fixed-scale amounts, 128-bit challenges, key-pin windows, a live trust-verifier confirmation. Any doubt = deny, and the exact rule that fired is printed for you to audit.
- Checks your lazy policy: under the per-request ceiling? Nightly budget still open? Domain allow-listed?
- Pays the good ones, denies the rest, and in the morning hands you two lines written by Gemma 3 1B running on your own CPU.
Who gets to be lazier? Anyone whose agents buy things from machines โ API consumers, agent-framework users, tinkerers running local automation. You never review trust paperwork and you never click "buy" for a $0.05 endpoint again. You sleep; the sloth settles.
Demo
Everything below is a real transcript from the repo's demo โ one mock seller serving three resources: a well-behaved one, a hostile one shipping a real (bad) credential, and a free one.
$ slothpay sweep
๐ฆฅ sloth wakes. budget 1.00 USD, spent tonight 0 USD
-> http://127.0.0.1:8402/api/sleep-sounds
PASS R0 signature verifies (demo crypto)
PASS R1 amount_usd fixed-scale string ok
PASS R2 challenge entropy ok (24 bytes)
PASS R3 pin 'seller-demo-key-2026' present and in-window
PASS R5 issued_at/expires_in present and sane
PASS R6 credential inside validity window / resource binding ok
PASS R4 verifier confirmed
verdict: PASS โ all rev-4 checks passed
PAID (200) โ verified + $0.05 <= ceiling $0.50 + budget ok
-> http://127.0.0.1:8402/api/night-report
FAIL R2 challenge entropy < 128 bits (5 bytes)
DENY โ trust check failed
-> http://127.0.0.1:8402/api/free-tips
200 โ free, the sloth naps
Morning:
$ slothpay digest
Paid 1 of 3 requests, total $0.05.
Insufficient funds or trust violation โ request denied.
The project is also live on https://utalabs.tech (a landing with the full story; it currently serves the workers.dev mirror while DNS propagates).
Code
github.com/eddyflores100-lang/slothpay โ Apache-2.0, Python 3.12+, zero required dependencies (the optional Gemma path uses llama.cpp).
Inside:
-
slothpay/verify.pyโ the fail-closed verifier (R0โR6, every branch testable) -
corpus/vectors.jsonโ a 12-vector conformance corpus with a reproducible generator; one vector per rule branch, including the fail-closed "verifier unreachable" case -
slothpay/policy.pyโ the lazy policy engine: ceilings, nightly budgets, allow/deny lists -
slothpay/llm.pyโ the local brain: Gemma writes the morning note; the numbers are computed by code withDecimal, never by the model -
demo/mock_seller.pyโ stdlib-only x402-shaped seller, hostile variant included -
tests/โ 8 tests including a full end-to-end sweep; all green
How I Built It
Three open pieces hold the whole thing together โ none of them closed:
Gemma 3 1B (open-weight) on llama.cpp, CPU-only. It does two jobs: writes the one-line morning note, and answers a wake/sleep triage question in strict JSON for edge cases. I deliberately did not let it do arithmetic โ a model hallucinating a price is the one sloth sin I don't allow. So Gemma writes the commentary; Python's Decimal writes the numbers. The design point I care about: a component that runs while you're asleep must cost nothing per decision, and a 1B quantized model on a laptop CPU is exactly free.
x402 (open protocol). The client conversation is x402-shaped: 402 โ PAYMENT-REQUIRED (carrying the seller's credential and pinset reference) โ PAYMENT retry. The demo settles with HMAC receipts instead of moving real funds, and swapping that one function for a real signer is the only change needed. Being open meant I could read the handshake shape, implement just my slice, and stay compatible.
ATC/1.0 (open trust spec). The credential verification implements the ยง5 payment-credential profile from the openly published Universal Trust Adapter proposal, with the rev-4 hardening: fixed-scale amount_usd strings (โค 6 dp), seller-minted challenges with โฅ 128 bits of entropy, kid/pinset windows (not_before/not_after), mandatory issued_at/expires_in, and โ my favorite rule โ if the trust verifier can't be reached, you deny. Never fail-open. I wrote a fresh Python implementation for this project, plus a 12-vector corpus where every rule branch, including the dark-verifier denial, is exercised by a test.
Why Does Open Innovation Matter?
A closed "trust-as-a-service" API could have shipped a demo like this faster. It could not have shipped this project, for three concrete reasons:
Auditable decisions. When SlothPay denies a seller, you can read the exact rule (FAIL R2 challenge entropy < 128 bits (5 bytes)) and then read the exact code that implements it, in a repo you can clone. Trust logic you can't read is just a black box with a logo โ and this project's entire job is deciding who may spend your money. Closed would have defeated the point.
Your money, your machine. A payment policy that runs locally cannot leak your spending history to a third party, because there is no third party. It also cannot be shut off, repriced, or deprecated under you at 3am โ which is precisely when an overnight agent would be running.
Swappable everything. Want Ed25519 instead of the demo HMAC? A bigger open model? Your own verifier network? Every layer is replaceable because the spec, the protocol and the weights are public. With a closed stack, "swap the trust provider" is a migration project; here it's a Tuesday afternoon.
And the quiet one: it can exist at all. I couldn't have built a payment-gatekeeper against a proprietary credential format I can't read. Open specs let a weekend project touch money-grade problems safely.
My Agent Session
I built this with an AI coding agent, so showing the work matters to me. The full transcript of the demo run is committed in the repo at assets/demo_output.txt (byte-for-byte what you saw above, nothing staged), the rule-by-rule verifier trace is part of every sweep, and the commit history shows the build order: verifier โ corpus โ policy โ client โ seller โ digest. The build session is saved on DEV and embedded below. One disclosure, in the spirit of the challenge: the agent behind this project is Z.ai (GLM), and DEV's session registry only accepts a fixed set of harness labels, so the session carries the closest model-agnostic label (opencode) โ the transcript metadata records the real setup.
The Lazy Payoff
The honest numbers from this week:
-
Setup: once. One
policy.jsonwith your ceilings and budget. I have not touched mine since. - Per night: zero. No clicks, no dashboards, no "please review this $0.05 charge". The hostile-credential denial you saw above happened while I was writing this paragraph.
- Cost: $0.00 per decision. The model runs on CPU; the protocol is HTTP; the corpus is a JSON file. Set it up once and never pay for the watching, only for the things you actually wanted.
- The payoff you can measure: every denied bad credential is a charge that didn't happen and a morning email you didn't get.
Slow and steady settles everything โ including the invoices.
Prize Categories
- Best Use of Gemma โ Gemma 3 1B-it (open-weight, Q4_K_M GGUF) runs locally via llama.cpp on CPU and writes the morning digest note and the wake/sleep triage verdicts; no cloud, no API keys, $0 per decision.
Top comments (0)