BETA — this is early software. APIs may change.
Give your AI agent a wallet it can't abuse.
Spend limits, approval flows, telegram alerts, real on-chain payments — one npm install. Built on OWS (wallets + policies) and MPP (pay any service over HTTP).
npm install agent-operator# interactive setup — creates agent-operator.json
npx agent-operator initimport { createOperator } from "agent-operator";
const operator = await createOperator();
const result = await operator.pay("my-agent", {
service: "https://api.example.com",
chain: "base",
maxBudget: 2,
});
console.log(`Paid: $${result.totalSpent}`);
console.log(`Tx: ${result.signature}`);
await operator.shutdown();All configuration lives in agent-operator.json. The CLI generates it, or create it manually:
{
"wallets": {
"my-agent": {
"walletId": "ows-wallet-id",
"chains": ["base", "solana", "tempo"],
"network": "testnet",
"tokens": {
"tempo": [
{
"address": "0x20c0000000000000000000000000000000000000",
"symbol": "pathUSD",
"decimals": 6
}
],
"base": [
{
"address": "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
"symbol": "USDC",
"decimals": 6
}
]
},
"policies": {
"dailyLimit": 50,
"sessionCap": 5,
"newCounterpartyHold": true,
"lowBalanceThreshold": 10,
"highValueThreshold": 200
},
"notifications": {
"provider": "telegram",
"botToken": "YOUR_BOT_TOKEN",
"chatId": "YOUR_CHAT_ID",
"alerts": {
"lowBalance": true,
"highValueTx": true,
"newCounterparty": true,
"policyDenied": true,
"dailySummary": true,
"sessionOpened": false
}
}
}
}
}One agent-operator instance manages multiple wallets. Each wallet has its own chains, policies, tokens, and notification provider.
| Field | Description |
|---|---|
walletId |
OWS wallet UUID |
chains |
Array of chains: "base", "solana", "tempo" |
network |
"mainnet" or "testnet" (Base Sepolia, Tempo Moderato, Solana Devnet) |
tokens |
Per-chain token addresses for balance tracking. Defaults: pathUSD (Tempo), USDC (Base), SOL (Solana) |
policies |
Spend limits and approval rules |
notifications |
Alert provider config per wallet |
Each connector handles real on-chain transactions for its chain:
- Base — builds ERC-20 USDC transfer, signs and broadcasts via OWS
signAndSend, returns real tx hash - Tempo — uses built-in
mppxsession method with payment channels, no native token (fees in TIP-20 stablecoins) - Solana — wraps
@solana/mppcharge method with OWS signing, returns tx signature
Connectors are resolved automatically from the wallet's chains array. Each enforces maxBudget — if the server charges more than your budget, the payment is rejected before signing.
| Chain | Mainnet | Testnet |
|---|---|---|
| Base | Base (8453) | Base Sepolia (84532) |
| Tempo | Tempo (4217) | Tempo Moderato (42431) |
| Solana | Mainnet Beta | Devnet |
The policy engine runs before every pay() call, in order:
- Session cap — reject if
maxBudget > sessionCap - Daily limit — reject if today's spend +
maxBudget > dailyLimit - High value gate — if above threshold, request human approval via Telegram
- New counterparty hold — if first-time service, request human approval
- Low balance alert — non-blocking notification if below threshold
Spend is tracked locally in ~/.agent-operator/spend.json.
Pluggable provider system. Each wallet can use a different provider.
Uses grammy with long-polling for approval flows. Included as a dependency — no extra install needed.
Approval messages show inline buttons (Approve/Reject). First response wins. Timeout (default 5 min) = rejected.
| Event | Trigger | Blocking? |
|---|---|---|
| New counterparty | First-time service URL | Yes — waits for approval |
| High value tx | maxBudget > highValueThreshold |
Yes — waits for approval |
| Policy denied | Any policy rejects payment | No |
| Low balance | Token balance < threshold | No |
| Daily summary | End of day | No |
import {
NotificationProvider,
AgentEvent,
ApprovalEvent,
ApprovalResult,
} from "agent-operator";
class MyProvider implements NotificationProvider {
name = "my-platform";
async start() {}
async stop() {}
async send(event: AgentEvent) {
/* fire-and-forget alert */
}
async sendWithApproval(event: ApprovalEvent): Promise<ApprovalResult> {
const approved = await askUser(event);
return { approved, approvalId: event.approvalId };
}
}npx agent-operator init # interactive setup, picks existing OWS wallets
npx agent-operator add-wallet # add wallet to existing config
npx agent-operator status # show wallets, balances, today's spendconst operator = await createOperator(); // reads ./agent-operator.json
const operator = await createOperator(path); // custom config path
// pay a service — returns { sessionId, totalSpent, signature }
const result = await operator.pay(walletName, { service, chain, maxBudget });
// get token balances — returns Balance[] per token
const balances = await operator.getBalances(walletName, chain);
// close an active session
await operator.closeSession(walletName, sessionId);
// list configured wallets
operator.getWalletNames();
// stop notification providers
await operator.shutdown();{
sessionId: string
totalSpent: number // actual amount charged by the server
refund?: number // maxBudget - totalSpent
signature?: string // real tx hash (Base) / channel ID (Tempo) / tx signature (Solana)
}agent code
|
v
operator.pay("my-agent", { service, chain: "base", maxBudget: 2 })
|
v
Policy Engine (in-process)
+-- session cap check
+-- daily limit check
+-- high value gate --> Telegram approval (if needed)
+-- new counterparty --> Telegram approval (if needed)
+-- low balance alert
|
v
BaseConnector
+-- receives 402 challenge from service (amount + recipient)
+-- rejects if amount > maxBudget
+-- builds real USDC transfer tx
+-- signs and broadcasts via OWS signAndSend
+-- returns tx hash
|
v
Spend Tracker
+-- records amount in ~/.agent-operator/spend.json
+-- returns SessionResult { totalSpent, signature }
No server. No KV. No separate process.
| Package | Role |
|---|---|
@open-wallet-standard/core |
Wallet management, signing, on-chain broadcast |
mppx |
MPP protocol client (Tempo built-in) |
@solana/mpp |
Solana MPP implementation |
grammy |
Telegram bot for notifications |
viem |
EVM transaction building and RPC |