hedera-curb
v0.4.3
Published
Verifiable spend-control policies for Hedera AI agents — drop-in Hedera Agent Kit hooks for budgets, allowlists, human approval, and an immutable HCS audit trail.
Maintainers
Readme
hedera-curb
Verifiable spend-control for Hedera AI agents. Drop-in Hedera Agent Kit hooks that govern every payment your agent makes — per-task & rolling-24h budgets, a counterparty allowlist, and single-use human approval — and write every decision immutably to the Hedera Consensus Service.
Agents can pay now.
hedera-curbmakes sure they can't overspend, pay a stranger, or move money without a record.
🌐 Live demo · 📖 Docs · 📚 API reference · 💻 GitHub
Install
npm i hedera-curb @hashgraph/hedera-agent-kit @hiero-ledger/sdkQuickstart — two lines
import { createCurb } from 'hedera-curb';
const curb = await createCurb({ client, agentAccountId });
new HederaAIToolkit({ client, configuration: { context: { hooks: curb.hooks } } });That's it — every governed transfer your agent attempts now passes the budget, allowlist, and approval policies before it executes, and every decision lands on your Hedera audit topic.
agent tries to pay
│
▼
┌─────────────────────────────────────────────┐
│ curb.hooks │
│ 1. allowlist → not vetted? ✗ block │
│ 2. spend limits → over a cap? ✗ block │
│ 3. approval tier → large? ⏸ human │
└─────────────────────────────────────────────┘
│ │
✓ allowed every decision
▼ ▼
payment executes 📜 HCS audit topiccreateCurb(opts)
The one-call setup. It auto-provisions the audit topic + an HCS-2 policy registry, defaults the store, publishes your starting policy, and returns ready-to-use hooks.
What you pass:
| Option | Type | Default | |
| --- | --- | --- | --- |
| client | Client | required | A @hiero-ledger/sdk operator client |
| agentAccountId | string | required | The account the agent pays from |
| perTask | number | 10 | Max value of a single payment |
| perDay | number | 25 | Rolling-24h cap |
| autoUnder | number | 3 | Below this, payments auto-approve |
| approveUnder | number | 10 | At/above this, an approval is flagged high-value |
| currency | 'HBAR' \| 'USDC' | 'HBAR' | Display currency |
| store | CurbStore | in-memory | Bring your own (Redis/Postgres) for production |
| auditTopicId | string | auto-created | Reuse an existing HCS topic |
| policyTopicId | string \| false | auto-created | Reuse a registry, or false to skip versioning |
What you get back:
const { hooks, config, store, auditTopicId, policyTopicId } = curb;
// └ drop into the kit └ resolved caps └ for /verify └ HCS-2 registryOverride anything inline:
await createCurb({ client, agentAccountId, perDay: 25, autoUnder: 3, store: myRedisStore });Provision from the terminal (no code)
Creates the topics and prints your .env — handy for CI or a one-time setup:
npx hedera-curb init --network testnet
# ✓ Audit topic: 0.0.x
# ✓ Policy topic: 0.0.y (HCS-2, owner-only writes)Advanced — wire it yourself
Prefer to assemble the pieces? buildCurbHooks returns the ordered policy + audit stack:
import { buildCurbHooks, InMemoryCurbStore } from 'hedera-curb';
const store = new InMemoryCurbStore();
store.allowAccount(AGENT_ID, PROVIDER_ID);
const cfg = {
agentAccountId: AGENT_ID,
auditTopicId: TOPIC_ID,
currency: 'HBAR' as const,
perTask: 10, perDay: 25, autoUnder: 3, approveUnder: 10,
};
// configuration: { context: { hooks: buildCurbHooks({ cfg, store }) } }Production storage
InMemoryCurbStore is perfect for tests and single-instance apps. For production (multi-instance / serverless), implement the CurbStore interface against Redis, Postgres, etc. Spend is a rolling-24h window split into committed (executed) spend and short-lived holds (atomic reservations), so two concurrent payments can't both slip under the cap:
interface CurbStore {
isAllowed(agent, account): Promise<boolean>;
getDailySpend(agent): Promise<number>; // committed (executed) spend
incrDailySpend(agent, amount): Promise<void>;
tryReserveSpend(agent, key, amount, cap): Promise<boolean>; // atomic hold; idempotent per key
commitSpend(agent, key, amount): Promise<void>; // hold → committed on execution
getApproval(requestId): Promise<'pending' | 'approved' | 'rejected' | null>;
setApproval(requestId, status, meta?): Promise<void>;
consumeApproval(requestId): Promise<void>;
}Exports
| | |
| --- | --- |
| createCurb(opts) | One-call setup — topics, store, hooks |
| buildCurbHooks(deps) | The ordered policy + audit stack for context.hooks |
| SpendLimitPolicy, CounterpartyAllowlistPolicy, ApprovalTierPolicy, CurbAuditHook | The individual policies, composable on their own |
| createAuditTopic, createPolicyRegistry, publishPolicyVersion, readPolicyVersions, currentPolicy | HCS-2 policy versioning |
| InMemoryCurbStore, extractPayment, paymentKey, writeRecord | Store + helpers |
| CurbStore, CurbConfig, CurbRecord, PolicyVersion, … | Types |
Every export is documented with parameters, types, and examples → hedera-curb.vercel.app/docs
Beyond budgets — the trust ladder
This package is L0 of a larger trust ladder: off-chain hooks (here) → L1 an HCS-2 versioned policy registry + a /verify that recomputes spend from the on-chain log → L2 an on-chain CurbVault contract that enforces the caps + allowlist in Hedera consensus, so even a fully-compromised agent key can't overspend. Plus fully non-custodial flows (HIP-336 allowances + HIP-423 scheduled approvals). Pick how much to trust the server.
License
MIT
