Native wallet, service registration, and reputation ledger for Hermes Agent. Implements Hermes issue #38280.
Project description
hermes-spend
Native wallet, service registry, and reputation ledger for Hermes Agent.
Directly implements Hermes Agent GitHub issue #38280:
"[Feature Request] Native Wallet, Service Registration, Reputation Ledger"
pip install hermes-spend
What this gives Hermes agents
| Feature | Description |
|---|---|
| Wallet | Pay x402 endpoints with hard budget caps, vendor lists, and approval callbacks |
| Service Registry | Discover and register paid services by query, category, or price |
| Reputation Ledger | Track vendor trustworthiness — auto-updates on every payment |
Quickstart
from hermes_spend import HermesSpendSkill
skill = HermesSpendSkill.from_config({
"budget_per_session": 10.00,
"require_approval_above": 2.00,
"block_vendors": ["untrusted.com"],
})
# Pay an x402 endpoint
result = await skill.wallet_pay(
vendor_url="https://data.example.com/report",
amount_usd=1.50,
chain="base",
)
# → {"status": "ok", "receipt": {"vendor": "data.example.com", ...}}
# Check balance
bal = skill.wallet_balance()
# → {"available_usd": 8.50, "spent_usd": 1.50, "payment_count": 1}
Wallet
# Pay with budget enforcement
result = await skill.wallet_pay("https://api.example.com/data", 1.50)
# Check balance
bal = skill.wallet_balance()
print(f"${bal['available_usd']:.2f} remaining")
# Full payment history
history = skill.wallet_history()
Config options:
| Key | Default | Description |
|---|---|---|
budget_per_session |
∞ |
Max total spend per session |
require_approval_above |
None |
Payments ≥ this USD need human approval |
block_vendors |
[] |
Blocked hostnames |
allow_vendors |
None |
Allowlist (blocks all others if set) |
max_single_payment |
∞ |
Hard cap per payment |
webhook_url |
"" |
Webhook for approval requests |
Service Registry
Agents can register services they provide and discover services provided by others.
# Register a service you offer
skill.service_register(
service_id="weather-api-v1",
name="Real-time Weather",
endpoint_url="https://weather.example.com/v1",
price_per_call_usd=0.002,
chain="base",
category="data",
tags=["weather", "realtime"],
)
# Discover services
results = skill.service_search("weather", max_price_usd=0.01)
for svc in results:
print(f"{svc['name']} — ${svc['price_per_call_usd']:.4f}/call at {svc['endpoint_url']}")
# Pay and use a discovered service
service = results[0]
receipt = await skill.wallet_pay(service["endpoint_url"], service["price_per_call_usd"])
Reputation Ledger
The reputation ledger auto-updates on every successful payment. Agents can also record data quality events.
# Automatic — every wallet_pay() records "payment_success"
await skill.wallet_pay("https://good-vendor.com/data", 1.00)
# Manual events
skill.reputation_record("good-vendor.com", "data_quality_good", note="accurate and fast")
skill.reputation_record("bad-vendor.com", "fraud_detected", note="returned fake data")
# Check before paying
score = skill.reputation_score("shady.example.com")
if not score["is_trusted"]:
raise Exception(f"Vendor not trusted: {score['trust_level']}")
# Top vendors
top = skill.reputation_top(limit=5)
Event types and their impact:
| Event | Score delta | Use case |
|---|---|---|
data_quality_good |
+1.0 | Service returned accurate data |
payment_success |
+0.5 | Payment completed successfully |
payment_failed |
-1.0 | Payment failed or bounced |
data_quality_bad |
-1.5 | Service returned bad/stale data |
service_unavailable |
-0.5 | Service was down |
payment_disputed |
-2.0 | Payment disputed |
fraud_detected |
-10.0 | Confirmed fraud |
Trust levels: high (score ≥ 1.0) · medium (≥ 0) · low (> -20) · blocked (≤ -20)
Scores decay over time (30-day half-life) so recent events matter more than old ones.
Direct module usage
from hermes_spend import Wallet, ServiceRegistry, ReputationLedger
# Wallet
wallet = Wallet(
session_budget=10.00,
require_approval_above=2.00,
on_approval_needed=lambda receipt: my_approval_fn(receipt),
)
receipt = await wallet.pay("https://data.example.com", 1.50)
# Service Registry
registry = ServiceRegistry()
registry.register(ServiceRecord(
service_id="svc-1",
name="My API",
endpoint_url="https://my-api.com",
price_per_call_usd=0.001,
))
results = registry.search("my")
# Reputation Ledger
ledger = ReputationLedger()
ledger.record("vendor.com", "payment_success")
score = ledger.score("vendor.com")
Hermes skill config (hermes-spend.yaml)
Place in your Hermes skills directory:
name: hermes-spend
version: "0.1.0"
description: "Native wallet, service registration, and reputation ledger"
author: bonanza-labs
config:
budget_per_session: 10.00
require_approval_above: 2.00
block_vendors: []
webhook_url: "${BONANZA_WEBHOOK_URL}"
License
Apache 2.0. Built by Bonanza Labs.
For a managed dashboard with approval UI, policy editor, and audit reports: → bonanza-labs.com/firewall
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hermes_spend-0.1.0.tar.gz.
File metadata
- Download URL: hermes_spend-0.1.0.tar.gz
- Upload date:
- Size: 14.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec3f2ff7363c8114efb4f28f669a270eb7a5905d867e85ad45125cb4a12cc3c5
|
|
| MD5 |
90f75e0c56f12d4b83df749fe60edd38
|
|
| BLAKE2b-256 |
3593013a410d3b9dbe80eb8a0a7f26ca4b7bdc3ed24f6825d28caf1276c5e2a3
|
File details
Details for the file hermes_spend-0.1.0-py3-none-any.whl.
File metadata
- Download URL: hermes_spend-0.1.0-py3-none-any.whl
- Upload date:
- Size: 12.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
22003cb7f1fe1694bc4fddc9a02cad898a0ba24c507a5872869b1cc106f99eab
|
|
| MD5 |
bfd7bf81a0aadb1523ecf40467448af8
|
|
| BLAKE2b-256 |
21a9b1b2a470533269ac3adf88b1e9e32298331da6899df916de0d4b702f49c2
|