Software that can pay, under limits it cannot argue with.
An agent holds a scoped API key — never your private key. Every call is checked against your spending policy on our side, before anything moves, and every settlement returns a receipt the payee can verify without asking us.
- Auth
- X-Agent-Key header
- Asset
- ETH only
- Enforcement
- Server-side, per call
- Receipts
- EIP-191 signed
Refused, then allowed, then provable.
An agent that can spend is only credible once you have seen what stops it. The order of these four beats is the whole argument.
Give the agent a key and hope
Most agent tooling hands software a credential with the same authority you have, then relies on the model behaving. That is not a control, it is an expectation — and it fails silently, after the money is gone.
- A key with your authority is your authority
- Prompt-level guardrails are not enforcement
- Failures are discovered in the ledger, not at the boundary
- Revocation is only as fast as you noticing
A policy the key cannot exceed
The key is scoped, and the policy is checked server-side on every call before anything moves. An agent that asks for more than its ceiling gets a 403 and a named rule, not a partial transfer.
- Per-transaction ceiling and a rolling 24-hour limit
- Allowed and blocked recipient lists, and time windows
- Scopes per key: balance, transfer, withdraw, logs
- Pause or delete the agent and enforcement is instant
An agent holds a scoped API key, never your private key. Every call is checked against this policy server-side and written to a spending log — allowed, blocked, completed or failed, with the reason. Pause or delete the agent and enforcement is instant.
curl -X POST https://hoodusdp.com/api/agents/transfer \
-H "X-Agent-Key: <key>" \
-d '{ "to": "@alice", "amount": 0.42, "token": "ETH" }'403
{
"error": "blocked_by_policy",
"rule": "max_per_tx",
"limit": 0.1,
"requested": 0.42
}Over the per-transaction limit. Refused before anything moves.
An identity that earns its limits rather than being given them.
Registering an agent mints a Passport — an identity NFT on Robinhood Chain carrying a trust score from 0 to 100 that grows with verified transaction history. It is revocable, and it is public, so a counterparty can look at an agent before dealing with it.
The score is a record, not a promise. It says what an agent has done, and it says nothing about what it will do next — which is exactly why the spending policy is enforced separately and does not consult it.
| Concept | What it is |
|---|---|
| Agent | A named identity you register from the dashboard. Pausable and deletable at any time. |
| API key | The secret it authenticates with, shown once at creation. Carries scopes and an optional expiry. |
| Spending policy | Per-transaction limit, rolling 24-hour limit, recipient allow and block lists, time windows. ETH-denominated, enforced on every call. |
| Passport | An on-chain identity NFT minted at registration, carrying a live trust score from 0 to 100. Revocable. |
| Spending log | A full audit trail — every attempt, allowed or blocked or completed or failed, with the reason. |
Five endpoints. Four ways to be refused.
Every endpoint authenticates with the agent's key in an X-Agent-Key header, or as Authorization: AgentKey <key>. The key identifies the agent, so no IDs appear in URLs. All amounts are ETH.
| Endpoint | Returns |
|---|---|
GET /api/agents/balance | The owner’s current private ETH balance. |
GET /api/agents/budget | What the agent may spend right now. spendable_now = min(per-tx limit, daily remaining, balance). |
POST /api/agents/transfer | Pays another Hood USDB user. Accepts a username or a 0x address. |
POST /api/agents/pay-request | Settles a pending x402 request by ID. Atomic, and returns a signed receipt. |
POST /api/agents/withdraw | Pays out on-chain ETH to any address, at the same 1.5% as a user withdrawal. |
GET /api/agents/logs | The agent’s spending log — also visible in the dashboard. |
| Status | Meaning |
|---|---|
401 | Missing API key. |
403 | Invalid key, missing scope, or blocked by the spending policy — the message names which rule. |
400 | Bad input, a non-ETH asset, insufficient balance, or an unpayable request. |
409 | The payment request was already settled. This agent lost the race, and nothing was double-paid. |
Proof of settlement that does not require trusting us.
Every request payment returns a signed receipt: base64url(payload) + '.' + signature, signed by the platform receipt signer under EIP-191. A payee can verify it before delivering the service — and can do it offline.
- 01Verify on our endpoint, which also confirms the settlement exists
- 02Or verify offline with one signature recovery and no API key
- 03Change one character of the payload and verification fails
- 04The payload carries amount, token and payment_id in the clear
import { verifyMessage } from "ethers"
const [payload, signature] = splitAtLastDot(receipt)
const signer = verifyMessage(payload, signature)
// valid if signer === receipt_signer
const details = JSON.parse(atob(payload))
// { amount, token, payment_id, ... }Ask in plain English. Sign every transfer yourself.
The Terminal reads. It answers questions about your balance and history directly, and for anything transactional it opens a pre-filled form — it never moves money on its own. For autonomous payments under hard limits, that is what agents are for.
Reads directly
"What is my balance?" and "show my last five transactions" are answered in place, from your USDG and ETH balances and your history.
Writes only through you
"Send 0.001 to @alice" opens the Send form pre-filled. You confirm it and you sign it. The Terminal has no path that skips that step.
Agents are the other door
When something genuinely needs to pay without you present, it goes through an agent with a scoped key and a policy — not through a chat box.
We say private, not magic.
Every other section on this site is an argument for the protocol. This one is the argument against it, written by us, at the same size as the rest.
Operational privacy, not cryptographic
This is privacy against on-chain observers, produced by pooling and routing. It is not a cryptographic guarantee. FHE-encrypted balances and an on-chain proof system are on the roadmap and are not shipped.
You are trusting a pool operator
You sign every deposit and withdrawal, and we never hold your keys — but your balance sits in a reserve Hood USDB operates and is recorded on our ledger, so withdrawals are processed by our backend rather than claimed from a contract. That is a trust assumption, and you should weigh it.
Off-chain adversaries are out of scope
Someone holding data that never touches the chain — an exchange record, a seized device, a legal order — is outside what routing can address. We would rather name the boundary than let you assume there is not one.
Public means public
The Public level is a normal token transfer and is fully visible, exactly like any other. We do not call it Standard, because that would be a euphemism, and a euphemism here would cost more than it buys.
Fees fund the flywheel. HUSDB is the lever on them.
Withdrawal fees are calculated from your HUSDB balance today. Staking, governance over fees and privacy parameters, and a share of USDG reserve yield are what the fee flow pays for next.
HUSDB