@mandate.md/sdk
v0.3.1
Published
Policy layer for agent wallets. Not a wallet — guardrails for existing wallets.
Maintainers
Readme
@mandate.md/sdk
Intent-aware policy layer for agent wallets. Validate why your agent wants to spend before it spends.
Install
bun add @mandate.md/sdk viem
# or
npm install @mandate.md/sdk viemQuick start
import { MandateClient } from '@mandate.md/sdk';
const client = new MandateClient({
runtimeKey: process.env.MANDATE_RUNTIME_KEY!,
});
// Validate before every transaction
const result = await client.validate({
action: 'transfer',
amount: '50',
to: '0xRecipient',
token: 'USDC',
reason: 'Invoice #127 from Alice',
});
if (result.allowed) {
// proceed with your wallet
}The reason field is where Mandate catches prompt injections, urgency pressure, and vague justifications that session keys can't see.
Register an agent
const { runtimeKey, claimUrl } = await MandateClient.register({
name: 'MyAgent',
evmAddress: '0xYourAgentAddress',
});
// Owner visits claimUrl to link agent to their dashboardError handling
import {
PolicyBlockedError,
ApprovalRequiredError,
CircuitBreakerError,
RiskBlockedError,
} from '@mandate.md/sdk';
try {
await client.validate({ action: 'transfer', amount: '500', reason: '...' });
} catch (err) {
if (err instanceof PolicyBlockedError) {
// err.blockReason: "exceeds_daily_limit", "address_not_allowed", etc.
// err.declineMessage: human-readable counter-evidence for the agent
}
if (err instanceof ApprovalRequiredError) {
// err.intentId, err.approvalId
// Transaction paused. Owner approves via dashboard/Telegram.
const status = await client.waitForApproval(err.intentId);
}
if (err instanceof CircuitBreakerError) {
// Agent frozen. Mismatch detected between validated and broadcast tx.
}
if (err instanceof RiskBlockedError) {
// On-chain risk: honeypot, malicious contract, flagged address
}
}Scan for unprotected calls
npx @mandate.md/cli scanOr use the Claude Code plugin: it scans automatically on every session start.
Exports
| Export | Description |
|--------|-------------|
| MandateClient | Validate transactions against spend limits, allowlists, reason analysis |
| MandateWallet | Full sign + broadcast flow for self-custodial wallets |
| PolicyBlockedError | Policy blocks the transaction |
| ApprovalRequiredError | Human approval needed |
| CircuitBreakerError | Agent frozen (envelope mismatch) |
| RiskBlockedError | On-chain risk detected |
| USDC | Token addresses (BASE_SEPOLIA, BASE_MAINNET) |
| CHAIN_ID | Chain IDs (BASE_SEPOLIA, BASE_MAINNET) |
Sub-path import for smaller bundle:
import { MandateClient } from '@mandate.md/sdk/client';CLI
npx @mandate.md/cli validate --action transfer --amount 50 --reason "Invoice #127"See @mandate.md/cli.
