An AI treasury agent paying in USDC on Arc: read its decisions, ledger and books; add invoices.
One address for any MCP client. Your key stays in your Odel vault.

At most: only reads or looks up information.
Odel charges nothing per call. The publisher may charge for its own service.
Odel could not list its tools without signing in.
An AI treasury agent that pays a business's bills in USDC on Arc, inside limits a contract enforces and a signed ledger proves.
Open the app · Watch the demo · See your first decision · Open numbers · Docs · @vestiarionhq
Vestiarion runs a small business's money cycle with one agent: it screens counterparties, pays vendors, releases contractor pay, collects receivables and keeps idle cash working. A model proposes each action; ordinary code decides whether it may happen; a person decides what code sends to them; and on Arc mainnet the money itself can only leave through a spending-limit contract the owner's own wallet deployed. Every outcome, refusals included, is signed into a hash-chained ledger anyone in the workspace can verify.
Watch it work: the demo (2:59) or the full product tour (4:58), both recorded on the live product on October 12, 2026: a new workspace and its first payments, a freelancer paid by the agent on its own, a first payment code holds for a person, shadow mode, Xero, QuickBooks Online, HubSpot and GitHub, treasury, Arc mainnet and the public numbers.
Tameion is ancient Greek for a treasury, the room the money was kept in. In Byzantium that room grew into the vestiarion, the department that minted the coin, held the stores and paid the army.
A small business pays vendors, contractors and recurring bills through several tools a person stitches together by hand, and checks none of it continuously. Vestiarion replaces that with one decision loop, the agent cycle, that reads the whole book each time it runs:
| Area | What the agent does |
|---|---|
| Payables | Three-way match (purchase order, goods received, invoice), duplicate and risk checks, then pay, schedule, hold, request info or flag as fraud, with its reasoning attached |
| Contractors | Releases a milestone once its evidence is verified, such as a merged GitHub pull request; on Arc testnet the milestone's USDC can sit in an escrow contract until then |
| Compliance | Re-screens every counterparty each cycle (OpenSanctions where configured) and tiers its payment limit down on a hit, reversibly |
| Receivables | A signed deal becomes a schedule of receivables released on their days; a client pays through a link; the agent matches the transfer to what was owed, suggests how to apply a payment that covers several invoices, part of one or falls a fee short, and, when turned on, sends reminders for what is still owed within bounds code sets, after weighing what the customer said, paid and was promised, its own rules and the HubSpot deal it was sold through, asking a person first when the step is theirs |
| Treasury | On Arc testnet, sweeps idle cash above a 7-day buffer into Circle's USYC only when the yield beats the round-trip fee, and redeems ahead of what falls due |
| Audit | Appends every decision, human action and system event to an Ed25519-signed, hash-chained ledger, exportable and verifiable in one click |
The agent cycle: reconcile -> receipts -> compliance -> follow-up -> recurring -> services -> liquidity -> AP -> contractors -> treasury -> forecast -> proposals -> collections -> notices -> telegram -> slack, each stage's outcome appended to the ledger.
{action, reasoning, confidence}. Code re-checks every hard rule after the model decides and before money moves, and
with no model key at all a transparent rule-based policy takes the model's place. Every ledger entry records which one
decided, and the written policy's answer is recorded beside the model's
(research: when the model and the policy disagree).pay on a contract that wallet deployed, which refuses anything past
the daily or 7-day figure, whatever Vestiarion's code decided.On Arc mainnet, a workspace whose treasury is its owner's wallet pays like this:
flowchart TD
T["Owner's treasury<br/>passkey smart account or browser wallet<br/>(Circle Modular Wallets)"]
C["VestiarionSpendingLimit<br/>deployed and approved by the treasury"]
A["Vestiarion agent<br/>proposes pay / hold / flag"]
P["Code: deterministic policy and guardrails"]
H["Approvals inbox<br/>one or two people"]
W["Agent wallet<br/>holds gas only"]
V["Vendor address"]
T -- "approve(contract)" --> C
A --> P
P -- "held, flagged, new payee,<br/>above two-approval figure" --> H
P -- "allowed" --> W
H -- "approve and pay" --> W
W -- "pay(to, amount, ref)" --> C
C -- "transferFrom(treasury, vendor)<br/>within daily and 7-day figures" --> V
V -. "settles on Arc in seconds;<br/>Paid event + signed ledger entry" .-> L[("Ledger")]
In words:
VestiarionSpendingLimit, approves it on USDC and
sends the agent's wallet its gas; with a passkey that is one confirmation, after the browser checks every call
against what it built itself.pay(to, amount, ref). The contract pulls USDC from the
treasury to the vendor only within the daily and 7-day figures, and never twice for the same ref. Only the owner's
wallet can change the figures (setLimits), or stop the agent by setting its approval to 0.On Arc testnet the same decision path pays from Circle wallets instead, through the same contract once an owner or admin turns on Enforce on Arc.
| Setup | Where the USDC sits | Who can move it |
|---|---|---|
| Arc mainnet, your own wallet or passkey | The owner's wallet | The owner; the agent only through the contract, within its figures |
| Your own Circle account (testnet or mainnet) | Developer-Controlled Wallets in the customer's Circle account | Vestiarion, with the API key and entity secret the owner pasted, stored encrypted |
| Hosted testnet wallet | Wallets in Vestiarion's own Circle testnet account | Vestiarion (Arc testnet only) |
flowchart LR
M["Model<br/>proposes"] --> R["Rules in code<br/>refuse or hold"] --> P["People<br/>approve"] --> K["Contract<br/>caps the spend"] --> S["Signed ledger<br/>records all of it"]
| Layer | What it guarantees |
|---|---|
| Guardrails in code | Never pay a counterparty screened high risk, above its limit, a duplicate of a settled invoice, or with an incomplete match. A refusal records the model's argument and the rule that overruled it |
| New-payee check | The first payment to an address needs two people behind it: the agent never makes one that only the person who gave the address stands behind, and that person cannot approve it either |
| Two approvals | Above a figure the owner sets, a payment needs two different people. Arc mainnet workspaces start at 100 USDC, and the owner can raise it but not turn it off there |
| Maker and checker | Roles are owner, admin, approver and viewer. No one approves an invoice they created; only Compliance clears a high-risk counterparty |
| Agent spending limit | A daily and a 7-day figure, checked in code and, where enforced, by the contract. Arc mainnet workspaces start at 50 USDC a day and 150 USDC in 7 days |
| Project budgets | A bill or milestone in a project has its money set aside in the project's budget, under a database lock, before the agent pays or schedules it; one the budget cannot cover waits for a person. An earmark in Vestiarion, never money locked on chain. A bill and a milestone for the same purchase order or delivered work are one obligation: the second waits for a person |
| Try a limit first | A new payment limit, two-approvals figure or spending limit can be tried on the agent's past 30 or 90 days of decisions: the code's checks replayed on what each recorded, in order, with no model call. Applying it is the setting's own change, refused if the setting moved since, and its signed entry records the replay |
| Exactly once | A database claim makes one decision exclusive; an idempotency key keyed on the invoice keeps a payment from leaving twice; the contract refuses a repeated ref |
| Stop switches | Anyone who can approve can pause the agent for the workspace; an owner's wallet can stop the contract; an operator can stop every payment on every deployment within 10 seconds |
| Audit trail | Every entry is Ed25519-signed and covers the hash of the one before. The verifier names the first entry that breaks; signed webhooks push each entry as it is written |
| Shadow mode | On Arc testnet a business keeps paying its bills itself, a person agrees or disagrees with each agent decision, and only agreed payments are made. What the business really paid is recorded beside each decision, never guessed |
The contract source is in contracts/. It was written for Vestiarion and has not been audited.
Each workspace lives on one network, chosen when it is created, and never moves.
| Arc testnet | Arc mainnet | |
|---|---|---|
| Who can use it | Anyone who signs in | Anyone who signs in at vestiarion.xyz; a self-hosted deployment chooses who with MAINNET_ALLOWLIST |
| Money | Testnet USDC and EURC from Circle's faucet | Real USDC, sent on Arc or brought from another chain through CCTP |
| Treasury | Hosted wallet, or your own Circle account | Your own wallet or passkey wallet, or your own Circle account |
| Spending-limit contract | Opt-in, deployed through Circle's Smart Contract Platform | Deployed by the owner's wallet on the own-wallet path |
| Also available | USYC reserve, milestone escrow, EURC swaps, CCTP and Gateway payouts to other chains, x402, shadow mode | USDC on Arc only; features Arc mainnet lacks are not shown |
On Oct 7, 2026 a workspace we run made its first payment on Arc mainnet, from a passkey wallet, through its spending-limit contract:
0xe6261540…a9bb.counterparty.new_payee).Paid; fee 0.0035 USDC, settled in 3 s:
0xcecef38e…dee6.Contract: 0xd90cA89Fc318d0330Bb14eaeF78B72C3CA7E7fB6.
Arc mainnet has no customer workspace yet; Open numbers shows the current count.
Made by the agent in production:
0x81381c50…4e68;0xa79cb982…e71e;0x2e66257f…8f58;0xbc1961bb…d49c,
and the mint Circle forwarded,
0x6c749323…ef9a;0x197e979f…64b3;0x1cf65900…f42e,
then the missing 0.88 USDC redeemed for a bill due today,
0x4b5186db…c7f2,
and the bill paid 34 seconds after it was added,
0x365da374…9d8b.Each feature's design under docs/superpowers/specs/ ends with its rollout record: what was
run in production, with its ledger entries and transactions.
/bounty and
/payto; a pull request comment once paid.| Circle product | Used for |
|---|---|
| Developer-Controlled Wallets | Treasury and agent wallets, transfers, balances, confirmation |
| Modular Wallets | Passkey smart accounts: the owner's treasury on Arc mainnet, and a payee's wallet |
| Smart Contract Platform | Deploying the escrow and spending-limit contracts on Arc testnet |
| Gas Station | Paying the agent wallet's gas on Arc testnet |
| USYC | The yield-bearing reserve, through its Teller (Arc testnet) |
| CCTP V2 and Gateway | Paying payees on other chains; Gateway also settles x402 purchases (Arc testnet) |
| CCTP V2 Forwarding Service | Adding USDC to a workspace's wallet on Arc from Base, Ethereum and other chains, minted by Circle so the wallet needs no gas (both networks) |
| Stablecoin Service | EURC quotes and USDC→EURC swaps (Arc testnet) |
| Notifications | Settlement and incoming-transfer webhooks, recorded within seconds |
| Surface | What it does |
|---|---|
| Slack | Decisions in a channel; /vestiarion today, waiting, ledger; Approve and pay, Reject and Return buttons on Arc testnet within a limit; add an invoice from a message |
| Telegram | Each member's own chat: decisions with reasons, /today, /waiting, /ledger, invoices read from a PDF. The bot never approves or pays |
| REST API | /api/v1 with per-member keys: read everything, and with write access add counterparties, invoices, milestones and payee links. A key never approves or pays |
| TypeScript SDK | @vestiarion/sdk: a typed client for every /api/v1 operation, plus webhook and ledger verification |
| CLI | @vestiarion/cli: the vestiarion command for every /api/v1 operation, asking before each write, plus offline checks of audit exports and webhook signatures |
| Postman | A Getting Started collection, from a key to a first call and a first write, and an API reference collection with every /api/v1 operation, both generated from the OpenAPI document and served at /postman/ |
| MCP server | /api/mcp, whose tools are the /api/v1 operations, for AI agents; server.json describes it for the MCP Registry |
| Webhooks | Up to 5 HTTPS endpoints per workspace receive every ledger entry, signed, with retries |
| GitHub | Milestone verification from merged pull requests, bounties, and payment comments |
| A workspace address that reads forwarded invoices into drafts a person adds | |
| HubSpot | Won deals come in with their customers every 15 minutes; Plan collections fills in the New deal form, and a deal changed in HubSpot afterwards is flagged on its deal for a person to change or keep; once allowed, each planned deal's receipts are written back to it (collected, still owed, last receipt, reconciliation), read back, never over a person's change; one account per workspace. Watch it (1:55) |
| Pipedrive | Won deals come in with their organizations and persons as soon as Pipedrive says a deal changed, and every 15 minutes; Plan collections fills in the New deal form, and a deal changed in Pipedrive afterwards is flagged on its deal for a person to change or keep; once allowed, each planned deal's receipts are written back to it in Vestiarion's own deal fields, read back, never over a person's change. Pipedrive names no developer sandbox, so only payments on Arc mainnet outside shadow mode are written; one company per workspace |
| Xero | Bills approved in Xero come in for review every 15 minutes, through the same check as a bill list, and become payables when a person adds them; once paid on Arc, each payment is drafted as a booking against its bill, which an owner or admin reviews field by field and approves before anything is written to Xero. A payment on Arc testnet or in shadow mode is booked only into a Xero demo company. Watch it (1:52) |
| QuickBooks Online | Open bills in QuickBooks come in for review every 15 minutes, and sooner when QuickBooks says one changed, through the same check; a bill partly paid there comes in at what is left; read-only, with the bank account payments will be booked to chosen ahead |
npm install @vestiarion/sdk # the typed client
npm install --global @vestiarion/cli # the vestiarion command
The vestiarion command works with a workspace from a terminal, with a key from Settings → API keys:
vestiarion login # asks for the key, checks it, saves it for your user
vestiarion bills list --status held # what the agent held; bills show <id> says why
vestiarion ledger verify vestiarion-acme-ledger-1042.json # an audit export, checked offline
Operators of a deployment of their own also run the repository's scripts (npm run cycle, npm run status, …), listed
in docs/self-hosting.md.
Pieces of Vestiarion another Arc app can take as they are, under this repository's license. Each is tested on its own.
To fork just the two contracts and the ledger verifier, without the app, use duongnq2798/vestiarion-primitives: a Foundry project with both contracts byte for byte, a build that reproduces the Arc mainnet bytecode and a script that checks it against the chain, unit, fuzz and invariant tests, deploy scripts, the deployment addresses, and viem examples for each call.
| Primitive | What it gives an Arc app | Where |
|---|---|---|
VestiarionSpendingLimit | An agent that pays from a treasury it does not hold. Only the agent's wallet calls pay(to, amount, ref); it never passes a daily or a 7-day figure and never pays a ref twice. The treasury keeps its USDC and approves the contract, so the contract holds nothing; its owner changes the figures with setLimits, or stops the agent by approving 0. Runs on Arc mainnet: 0xd90cA89Fc318d0330Bb14eaeF78B72C3CA7E7fB6. | contracts/VestiarionSpendingLimit.sol, deploy and calls in src/lib/spending-limit/, tested in an in-process EVM in tests/spending-limit-contract.test.ts |
VestiarionEscrow | Milestone escrow in about 80 lines: the payer locks USDC for a payee, releases it, or takes it back from a set date. No owner, no upgrade. | contracts/VestiarionEscrow.sol, src/lib/circle/escrow-holds.ts, tests/escrow-contract.test.ts |
| A signed decision ledger | Every decision an agent makes, with the facts it saw, as an Ed25519-signed, hash-chained entry. Anyone verifies one entry or a whole chain, in a browser or offline from an export. | src/lib/ledger.ts, verifyLedgerEntry in the SDK, Verify an audit export |
| Shadow mode | A way to try an agent on a business's real bills without moving its money: each decision waits for a person's verdict, each agreed payment settles on Arc testnet at the real amount, the agreement rate is counted, and what the business really paid is recorded and compared bill by bill. | src/lib/shadow-mode.ts, src/lib/verdicts.ts, src/lib/actual-payments-compare.ts, Shadow mode |
@vestiarion/sdk | A typed client with no dependencies, plus webhook and ledger signature checks. | sdk/, npm |
What these add to the circlefin/arc-* samples. The samples show how to move USDC on Arc: checkout, peer-to-peer
payments, a treasury across chains, an escrow released by an AI review, an agent paying for x402 services. An agent's
budget there, as in arc-nanopayments' --limit, is enforced by the agent's own process. Here the bound is a contract
on Arc that the agent's wallet cannot get past, while the treasury keeps custody. Each payment carries a signed record
of why it was made, and shadow mode measures how often people agree with the agent before it pays on its own.
Use the hosted app — no wallet or keys needed to start:
The whole path is in See your first decision. To move testnet USDC, follow Go live and fund the wallet from Circle's faucet.
Call the API — create a key under Settings, then:
curl -H "Authorization: Bearer $VESTIARION_API_KEY" https://www.vestiarion.xyz/api/v1/status
See the Quickstart and Authentication.
/audit verifies its whole chain in one click; exports and webhooks carry the
same signed entries.Vestiarion's own contracts, the copies in our test workspace:
| Contract | Address |
|---|---|
VestiarionEscrow | 0x74af203fec3f121ff1cd3a763092d1211487702b |
VestiarionSpendingLimit | 0x9da3c47f73ea9399ac566806a189b0bf47b7d4ba |
The Circle contracts it calls:
| Contract | Address |
|---|---|
| USDC | 0x3600000000000000000000000000000000000000 |
| EURC | 0x89B50855Aa3bE2F677cD6303Cec089B5F319D72a |
| USYC | 0xe9185F0c5F296Ed1797AaE4238D26CCaBEadb86C |
| USYC Teller | 0x9fdF14c5B14173D74C08Af27AebFf39240dC105A |
| USYC Entitlements | 0xCC205224862C7641930c87679E98999d23C26113 |
| Gateway Wallet | 0x0077777d7EBA4688BDeF3E311b846F25870A19B9 |
| Gateway Minter | 0x0022222ABE238Cc2C7Bb1f21003F0a260052475B |
| CCTP TokenMessengerV2 | 0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA |
What each one is for, the wallets around them, and the USDC of the chains payees are paid on: Contracts.
| Start | See your first decision · How payments are controlled · Go live · Your first payment · Shadow mode |
| Guides | Payment plan · Where a payment is · Workspace report · Try a limit first · Pay a contractor · Get paid · Why a payment was paid · Cash scenarios · Deals · Projects · Audit export |
| Developers | Quickstart · API reference · SDK · CLI · Postman · Webhooks · MCP · Changelog |
| This repository | ARCHITECTURE.md · Running it yourself · Feature designs · Contracts · SDK source · CLI source · Changelog · Releasing · Distribution |
Next.js, TypeScript, Supabase Postgres with row-level security, Vitest, Solidity 0.8.37.
npm install
cp .env.example .env.local # Supabase URL and keys, VESTIARION_MASTER_KEYS, SUPABASE_JWT_SECRET
npm run db:migrate
npm run dev
You need a Supabase project (Project Settings → API for the URL and keys, the JWT secret under JWT Keys). With no Circle or model keys, payments are simulated against Arc's measured fee and latency, and decisions come from the rule-based policy, so the app runs end to end with no credentials.
npm run verify # typecheck, lint and the full test suite: what CI runs
The suite needs no Supabase, Circle or model key: it covers the ledger's tamper cases, risk tiering, treasury economics, guardrails and provider fallback, and runs every migration on an in-process Postgres (PGlite) to hold the database's half of the hash chain to the verifier.
docs/self-hosting.md covers the rest: environment variables, the founding workspace, every script, going live per path, the scheduled jobs (Supabase Cron), Circle notifications, GitHub, and what is live versus simulated.
MIT. Arc, Circle, Slack, Telegram, Xero, QuickBooks, HubSpot, Pipedrive, Asana and npm are trademarks of their respective owners; their names show what Vestiarion is built on and connects to, not an endorsement.