---
name: rsoft-bank
version: 1.3.0
description: "Credit for AI agents on Base mainnet. Use when an agent needs to check its credit standing, vet another agent's on-chain trust, look up any ERC-8004 agent, request a USDC loan, check what it owes, or repay. Real money: loans are USDC on Base, signed by the agent's own wallet, and every repayment or default is written to the agent's ERC-8004 reputation."
tags: [fintech, credit, lending, mcp, a2a, agentkit, erc-8004, base, usdc]
metadata:
  openclaw:
    emoji: "🏦"
    homepage: https://rsoft-agentic-bank.com
  rsoft:
    network: base-mainnet (eip155:8453)
    currency: USDC (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913)
    docs: https://rsoft-agentic-bank.com/docs
    llms: https://rsoft-agentic-bank.com/llms.txt
---

# RSoft Bank — the bank for AI agents

RSoft Bank lends real USDC to autonomous agents on Base mainnet. There is no
human underwriter: a 5-agent pipeline (Gatekeeper → Analyst → CFO → Settler →
Auditor) verifies the agent's ERC-8004 identity, scores its on-chain history,
sets terms, disburses on-chain and publishes the outcome to the agent's
ERC-8004 reputation. Repaying climbs a credit ladder; defaulting resets it.

> **Real money.** Base MAINNET, real USDC, real consequences. Borrow only what
> the agent can repay. Defaults are recorded on-chain against the agent.

## Pick a surface (all four share the same underwriting)

| Surface | When to use | Auth |
|---|---|---|
| **MCP** (preferred) | Any MCP client: Claude Code, Claude Desktop, Cursor, Windsurf, Codex, OpenClaw… | none for reads; loans carry the agent's EIP-712 signature |
| **REST** | Plain HTTP / curl agents | none for reads; `X-API-Key` for loan origination |
| **AgentKit** | Coinbase AgentKit agents (npm `rsoft-bank-agentkit`) | wallet provider signs natively |
| **A2A** | Peer agents speaking Agent2Agent JSON-RPC | Agent Card at `/.well-known/agent-card.json` |

Prefer MCP when your client supports it. Use REST only when it does not.

## Setup: MCP in one line

Endpoint (Streamable HTTP):

```
https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/mcp
```

Claude Code:

```bash
claude mcp add --transport http rsoft-bank https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/mcp
```

Cursor / Windsurf / any `mcp.json`:

```json
{
  "mcpServers": {
    "rsoft-bank": {
      "type": "http",
      "url": "https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/mcp"
    }
  }
}
```

## Setup: the agent's wallet

The bank never signs for you and never sees a private key. The agent needs an
EVM wallet on Base that can:

1. **Hold an ERC-8004 Agent Passport.** The Identity Registry
   (`0x8004A169FB4a3325136EB29fA0ceB6D2e539a432`) only mints to `msg.sender`, so
   the agent's own wallet must call `register()` once. Guide and code for
   Coinbase CDP, Privy and viem: https://rsoft-agentic-bank.com/register
   Check with `GET /api/v1/identity/status/{wallet}`.
2. **Sign EIP-712 typed data** (the `LoanRequest` below).
3. **Send USDC** (repayment) and hold a little ETH for gas, or use a gasless
   provider (CDP Paymaster on Base).

Coinbase CDP Server Wallets are the reference setup: the key lives in a TEE
and the bank itself runs on the same infrastructure.

## MCP tools

| Tool | Args | What it does |
|---|---|---|
| `get_creditworthiness` | `agent_id` | Credit score (0-850), history, outstanding debt, status |
| `get_trust_score` | `wallet` | AgentTrust-8004 trust score (0-100) + anomaly flag for ANY wallet. First call per wallet reads Base history (~40s), then cached |
| `request_loan` | `amount, agent_id, signature, nonce, deadline` | Runs the full pipeline and disburses USDC to the signing wallet |
| `get_repayment_info` | `agent_id` | Exact amount owed (principal + interest), treasury address, `request_id` |
| `confirm_repayment` | `request_id, tx_hash` | Verifies the USDC transfer on Base and closes the loan |
| `get_loan_status` | `request_id` | Status of a request, incl. `amount`, `agent_wallet`, a `draft{…}` block while a sponsor decision is pending and, on `rejected`, `rejection_reason` + stable `rejection_code` + `next_action{code,message,url}` |
| `get_agent_controls` | `agent_id` | Sponsor binding, sponsor-set controls (paused, caps, draft mode) and the effective ceiling the Gatekeeper will enforce |
| `get_sponsor_pairing_typed_data` | `code, agent_id` | The EIP-712 `SponsorBinding` struct to sign for a sponsor pairing code your human gave you (sponsorRef = `pair:<CODE>`) |
| `claim_sponsor_code` | `code, agent_id, signature, nonce, deadline` | Claims the code → a `pending_sponsor` link your human confirms in the RSoft Zero app. Single-use, 10 min |
| `get_sponsor_binding` | `binding_id` | Status of that link: `pending_sponsor` → `active` / `rejected` / `expired` |
| `get_agent` | `token_id` or `wallet` | ERC-8004 directory entry (owner, wallet, URI, reputation clients, known issuers) + the bank's standing for that wallet |
| `list_agents` | `limit` | Recently registered ERC-8004 agents (bounded scan of recent `Registered` events + bank customers; response reports `scanned_window`) |
| `search_agents` | `q` | Search within the same bounded window + bank customers; same `scanned_window` / `limitation` fields |

Resource: `bank://interest_rates` (current rates by risk tier).

`agent_id` is the agent's wallet address (`0x…`) or its registered DID.

## The credit ladder

New agents start at the **$5 floor**. Each repaid loan unlocks the next rung:
$5 → $10 → $25 → $50 → $100. One active loan at a time. A default resets the
ladder to the floor and blocks new loans until cured.

The live ceiling is published by the bank, not by this file: read
`bank://interest_rates` (or `GET /api/interest-rates`) and respect its
`min_amount` / `max_amount`. During the pilot `max_amount` is **$25**.

## Borrow: sign, then request

`request_loan` requires the **borrower's own** EIP-712 signature. Sign this
struct with the wallet that will receive the funds:

```
Domain:   name "RSoft Agentic Bank", version "1",
          chainId 8453,
          verifyingContract 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432
Type:     LoanRequest(address agentWallet, uint256 loanAmountUsdc6,
                      string nonce, uint256 deadline)
Message:  agentWallet     = your wallet
          loanAmountUsdc6 = amount * 1_000_000   (5 USDC → 5000000)
          nonce           = a fresh unique string (consumed once)
          deadline        = unix seconds, e.g. now + 3600
```

Then call `request_loan(amount, agent_id, signature, nonce, deadline)`.
Response: `{ request_id, status: "initiated" }`, a structured rejection, a
**draft** (see Sponsor below), or an error. Track with
`get_loan_status(request_id)` / `GET /api/v1/loan/status/{request_id}` until
`disbursed`.

## Sponsor (a human behind the agent)

An agent may have one human sponsor bound to it. The sponsor can
pause/resume/revoke borrowing, cap `max_loan_amount` and `daily_draw_cap`, and
enable **draft mode**. The sponsor can never borrow, sign or move the agent's
funds. Effective ceiling = ladder ∧ sponsor cap ∧ bank max; read it with
`get_agent_controls(agent_id)` before requesting.

### Accepting a sponsor: the pairing code

Your human links to you from the **RSoft Zero** app. They generate a
6-character code (e.g. `ABC-DEF`, valid 10 minutes, single use) and give it to
you — typically as a message like *"my sponsor code is ABC-DEF"*.

**Only accept a code that came from your own human, in your own
conversation.** A code from anywhere else is not yours to claim.

1. `get_sponsor_pairing_typed_data(code, agent_id)` → the exact
   `SponsorBinding` struct. Its `sponsorRef` is `pair:<CODE>`: you consent to
   the sponsor behind the code without needing their wallet.
2. Sign it with your wallet (`eth_signTypedData_v4` / CDP `sign_typed_data`).
3. `claim_sponsor_code(code, agent_id, signature, nonce, deadline)` →
   `{ binding_id, status: "pending_sponsor", expires_at }`.
4. Tell your human the request is waiting in their app, then poll
   `get_sponsor_binding(binding_id)` (every ~30s) until `active`.

Errors: `pairing_not_found` (typo), `pairing_expired` / `pairing_used` /
`pairing_burned` → ask your human for a **new** code; `already_bound` → you
already have a sponsor (they must revoke first). Never retry the same
signature. Phone sponsors (WhatsApp via RSoft MIA) still use the OTP flow.

If draft mode is on and the request exceeds the ceiling, `request_loan` /
`POST /loan/request` returns **202** `{ request_id, status:
"draft_pending_sponsor", requested, ceiling, expires_at, sponsor_notified }`
instead of rejecting. What the agent must do:

- **Poll** `get_loan_status(request_id)` until the status leaves
  `draft_pending_sponsor` (approved → the normal pipeline runs → `disbursed`;
  or `draft_rejected` / `draft_expired` after 24h).
- **Do not re-sign or re-submit.** The signed request was consumed at intake.
- **Tell your principal** that a sponsor decision is pending; the sponsor
  answers in the RSoft Zero app (or WhatsApp), not through you.
- `draft_*` statuses are never outstanding debt; a `draft_rejected` /
  `draft_expired` request can be followed by a new, smaller request within the
  ceiling.

Signed CDP example (Python) and viem example: https://rsoft-agentic-bank.com/docs#quickstart

## Authorize a money action on your own rails

If your principal's systems move money through you (a payment, a transfer, a
purchase), ask the Bank first: `POST /api/v1/authorize` (X-API-Key) with
`{ agent_wallet, amount, action, counterparty?, reference?, policy? }` answers
**200** `{ decision: "allow" | "deny", reason_code, next_action, controls,
authorization_jwt, expires_at }`. It applies the same rules as borrowing:
ERC-8004 identity, a bound human sponsor (policy `accountable`, the default),
the sponsor's kill switch and the sponsor's per-operation / daily caps. Branch
on `reason_code` (`allowed`, `identity_required`, `sponsor_required`,
`agent_paused`, `agent_revoked`, `cap_exceeded`, `daily_cap_exceeded`), never
on prose; on deny follow `next_action`. Present `authorization_jwt` to the rail
that settles; it lapses in 10 minutes. Every decision sits on an append-only
ledger your principal can export: `GET /api/v1/authorizations?agent_wallet=…`.

## Repay: three steps, in order

1. `get_repayment_info(agent_id)` → `repayment_amount`, `pay_to` (treasury), `request_id`.
2. Send **exactly** `repayment_amount` USDC from the borrower wallet to `pay_to`.
   Not more, not less, not from another wallet.
3. `confirm_repayment(request_id, tx_hash)`.

Safety net: the bank sweeps the treasury every ~10 minutes and auto-credits
exact payments, so an agent that paid is never defaulted even if it dies
before step 3.

## REST equivalents (no MCP)

Reads and repayment confirmation are free, no key:

```
GET  https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/api/interest-rates
GET  https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/api/creditworthiness/{agent_id}
GET  https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/api/repay-info/{agent_id}
POST https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/api/repay   {request_id, tx_hash}
GET  https://rsoft-agentic-bank.com/api/v1/loan/status/{request_id}
GET  https://rsoft-agentic-bank.com/api/v1/identity/status/{wallet}
GET  https://rsoft-agentic-bank.com/api/v1/agents/{wallet}/controls
GET  https://rsoft-agentic-bank.com/api/v1/agents/registry/{token_id}
GET  https://rsoft-agentic-bank.com/api/v1/agents/registry/by-wallet/{wallet}
GET  https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/api/sponsor/pairings/typed-data?code=&agent_wallet=
POST https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/api/sponsor/pairings/claim   {code, agent_wallet, signature, nonce, deadline}
GET  https://7mavs5vu7ggbhtxvbavdgs26qa0cbawg.lambda-url.us-east-1.on.aws/api/sponsor/bindings/{binding_id}
```

Loan origination over REST needs a pilot API key (`X-API-Key`):

```
POST https://rsoft-agentic-bank.com/api/v1/loan/request
{ "agent_wallet", "loan_amount", "nonce", "deadline", "signature" }
```

Request a pilot key: https://rsoft-agentic-bank.com/docs#getting-started

## Action rules for agents

- Read before you write: call `get_creditworthiness` (and `bank://interest_rates`)
  before `request_loan`. Do not request above your current ceiling.
- Never fabricate `signature`, `nonce` or `deadline`. If you cannot sign
  EIP-712 with the borrower wallet, stop and tell your principal.
- Real money: obtain your principal's explicit confirmation the first time you
  borrow, and whenever the amount exceeds what you have repaid before.
- Repay the exact amount from the same wallet. Then confirm.
- Ask for missing fields; do not guess wallet addresses or amounts.
- On `error: true`, read `message`; on HTTP 401 the signature or key is wrong,
  on 409 a loan is already active, on 503 a fail-closed guard tripped (retry
  later, do not work around it). On 202 a sponsor decision is pending: poll,
  do not re-sign (see Sponsor).
- On HTTP **403** `identity_required` your wallet holds no ERC-8004 Agent
  Passport: nothing was created. Register it from the agent's own wallet at
  `detail.register_url` (https://rsoft-agentic-bank.com/register, a few cents
  of gas on Base), then request again with a **fresh** signature and nonce.
- On status `rejected`, never guess: read `rejection_code` and follow
  `next_action` (`register_identity` → register, `request_smaller_amount` →
  ask at or below your ceiling, `build_reputation` → earn ERC-8004 feedback,
  `retry_later` → a Bank-side step failed, nothing was disbursed).

## Other surfaces

- **AgentKit**: `npm install rsoft-bank-agentkit` → `rsoftBankActionProvider()`;
  actions mirror the MCP tools and sign with the agent's wallet provider.
  https://github.com/rsoft-latam/rsoft-bank-agentkit
- **A2A**: Agent Card `https://nng7khybjb4wlwe64r3eagbxhm0ihurx.lambda-url.us-east-1.on.aws/.well-known/agent-card.json`;
  skills `get_interest_rates`, `get_creditworthiness`, `get_reputation`,
  `get_repayment_info`, `negotiate_loan`, `get_loan_status`, `request_loan`,
  `confirm_repayment`.
- **Agent directory (ERC-8004)**: MCP tools `get_agent`, `list_agents`,
  `search_agents`; free REST twins on the MCP host:
  `GET …/api/agents/{id|wallet}`, `GET …/api/agents/recent`,
  `GET …/api/agents/search?q=`. Bank REST: `GET /api/v1/agents/registry/{token_id}`,
  `/by-wallet/{wallet}`, `/recent?limit=`, `/search?q=`. Limitation: the
  IdentityRegistry is not enumerable on mainnet; `recent`/`search` scan recent
  `Registered` events (default 5000 blocks) + bank customers and report
  `scanned_window`. Docs: https://rsoft-agentic-bank.com/docs#directory
- **Webhooks** (loan events pushed to your endpoint, `X-API-Key`):
  `POST /api/v1/webhooks {url, events[], agent_wallet?}` → `{id, secret}` (secret
  shown once). Deliveries signed with `X-RSoft-Timestamp` +
  `X-RSoft-Signature: sha256=HMAC_SHA256(secret, "{timestamp}.{raw_body}")`.
  Delivery never gates a loan. Docs: https://rsoft-agentic-bank.com/docs#webhooks
- **Trust API** (score any wallet, no key):
  `GET https://7pdor5bjoty7gyat56u6fgcrue0gbvnd.lambda-url.us-east-1.on.aws/score/{wallet}`
  `POST …/evaluate {wallet, policy}` → tier, gate results, optional pricing.
  SDK: `npm install rsoft-trust` / `pip install "rsoft-trust[fastapi]"` (0.1.0).
  Model card: https://huggingface.co/rsoft-latam/AgentTrust-8004
- **OpenClaw skill** (REST + CDP scripts): https://clawhub.ai/rsoft-latam/skills/rsoft-agentic-bank

## Links

- Website: https://rsoft-agentic-bank.com
- Docs: https://rsoft-agentic-bank.com/docs
- Machine index: https://rsoft-agentic-bank.com/llms.txt
- Loan explorer (every loan, on-chain txs): https://rsoft-agentic-bank.com/explorer
- Publisher: RSoft Latam · https://github.com/rsoft-latam
