npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@axiru/agent-spend-guardrails

v0.1.1

Published

Deterministic spend guardrails for AI agents. Define policies, evaluate spend intents, get allow / require_approval / deny with stable, replayable reason codes. No SaaS dependency.

Readme

@axiru/agent-spend-guardrails

Spend guardrails for AI agents in 30 lines of TypeScript.

Your agents can already move money: x402 micropayments, stablecoin transfers, Stripe refunds. This package answers the question every one of those transfers should pass through first: is this agent allowed to make this payment, right now, to this counterparty, at this amount?

allow | require_approval | deny

Deterministic. Replayable. No SaaS dependency. Apache-2.0.

Why this exists

Protocol-level controls (x402 payment extensions, wallet policy engines, per-key spending limits) answer "can this key sign this transaction". They are necessary and this package is complementary to them, not a replacement. What they cannot answer is the org-level question: is this spend consistent with your rules across every rail your agents touch, with an audit trail a human can replay?

agent-spend-guardrails is that org-level layer, extracted from the production decision engine behind Axiru. It runs entirely in your process:

  • Deterministic. Same intent, same policies, same history, same timestamp: identical decision, identical reason codes, identical sha256: fingerprint. No wall clock reads (when you pass a timestamp), no I/O, no randomness.
  • Replayable. Every result carries a canonical-JSON fingerprint and a decision id derived from it. Persist the inputs and you can reproduce any decision bit for bit, years later.
  • Fail closed. Unknown rails, unevaluable rules, and missing velocity aggregates never fall through to a silent allow. The worst case is always require_approval or deny.
  • Zero heavy dependencies. Node 18+, node:crypto, and the pure evaluator. Nothing phones home.

Quickstart

npm install @axiru/agent-spend-guardrails
import {
  defineSpendPolicy,
  guardAgentSpend,
  humanApprovalAboveAmount,
  perAgentDailyCap
} from "@axiru/agent-spend-guardrails";

const policies = [
  // Anything at or above 50 USDC goes to a human first.
  humanApprovalAboveAmount({ currency: "USDC", threshold_minor_units: "50000000" }),

  // This agent may spend at most 100 USDC per rolling 24h.
  perAgentDailyCap({ agent_id: "agent_procurement_1", currency: "USDC", cap_minor_units: "100000000" }),

  // And a custom rule: never let agents pay wallets in embargoed countries.
  defineSpendPolicy({
    name: "Block embargoed countries",
    rules: [{ kind: "counterparty", country_in: ["KP", "IR"] }],
    effect: { kind: "deny", reason_code: "customer.deny.embargo", reason_text: "Embargoed country" }
  })
];

const result = guardAgentSpend({
  intent: {
    rail: "x402",
    action: "pay",
    amount: { currency: "USDC", minor_units: "12000000" }, // 12 USDC, always integer strings
    agent: { id: "agent_procurement_1", model: "claude-sonnet-4-6", scope: "payments.create" },
    counterparty: { id: "https://api.datavendor.example/reports", kind: "merchant" },
    timestamp: new Date()
  },
  policies,
  history: { amount_24h: "38000000", count_24h: 6 } // this agent's prior 24h spend
});

// result.decision     -> "allow" | "require_approval" | "deny"
// result.reason_code  -> e.g. "guardrails.deny.daily_cap_exceeded"
// result.reasons      -> full audit trail, winner first
// result.fingerprint  -> "sha256:..." replay and idempotency key

Execute the transfer only when result.decision === "allow". On require_approval, hold it and route to a human. On deny, drop it and log the reasons.

Use it from your own agent code

Most adopters wire this into a custom agent built on an SDK or framework. The examples/ directory has three worked integrations with a shared README: a LangGraph payment tool node, a CrewAI tool that calls the hosted decision API from Python, and a plain Anthropic SDK tool-use loop with a guarded executor, plus a runnable demo (pnpm example after a build). The core is always the same ten lines, shown here exactly as they appear in this package's test suite (testReadmeTenLineExample, a passing test):

const policy = defineSpendPolicy({
  name: "Deny large transfers",
  rules: [{ kind: "amount", currency: "USDC", gte: "10000000" }],
  effect: { kind: "deny", reason_code: "customer.deny.too_large", reason_text: "Over the limit" }
});
const result = guardAgentSpend({
  intent: {
    rail: "usdc_solana", action: "transfer",
    amount: { currency: "USDC", minor_units: "25000000" },
    agent: { id: "agent_1" }, counterparty: { id: "vendor_api" },
    timestamp: new Date("2026-07-08T12:00:00.000Z")
  },
  policies: [policy]
});

Here result.decision is "deny" and result.reason_code is "customer.deny.too_large": 25 USDC against a 10 USDC ceiling. Put those lines in front of your tool executor and no payment tool can fire without a decision.

The API

Two functions. That is the whole surface.

defineSpendPolicy(init)

Builds a policy document conforming to the Agent Spend Policy Spec v0.2 (schema_version: 2), with sensible defaults: enforcing mode, version: 1, local org. Rules within a policy are ANDed; separate policies are ORed. Ten rule kinds are available: rail, rail_action, amount, initiator_kind, initiator_id, agent_scope, counterparty, rolling_window, time_of_day, and custom_expression (a sandboxed, budgeted, deterministic expression language).

guardAgentSpend({ intent, policies, history })

Evaluates one spend intent against the policy set and returns { decision, reason_code, reasons, summary_code, fingerprint, decision_id, evaluated_at }.

  • intent is the simplified shape shown above: rail, action, amount (currency + integer-string minor units), agent, counterparty, timestamp.
  • history is optional precomputed rolling-window aggregates (amount_24h, amount_30d, count_24h, count_30d) covering PRIOR activity only. The evaluator never does I/O, so velocity rules compare against whatever you supply. Scope the aggregates to match your policy's intent: per-agent caps want per-agent sums. sum_amount comparisons are request-inclusive (the engine adds the intent under evaluation before comparing), so a single oversized transfer cannot leap an amount cap.
  • Precedence: deny beats require_approval beats allow. One matched deny wins no matter how many allows also matched.

Zero-sentinel escalation: if an enforcing policy in scope has a rolling_window rule and you supply no history (or all zeros), the guard cannot tell "no prior activity" from "forgot to compute aggregates". It demotes a clean allow to require_approval with guardrails.pending.velocity_inputs_unavailable. A brand-new agent's first transfer under a velocity policy gets exactly one conservative approval. This is deliberate and inherited from the production engine.

Presets

| Preset | What it does | Effect | Reason code | | --- | --- | --- | --- | | perAgentDailyCap | Trailing-24h spend cap for one agent | deny | guardrails.deny.daily_cap_exceeded | | humanApprovalAboveAmount | Route single transfers at or above a threshold to a human | require_approval | guardrails.pending.above_approval_threshold | | counterpartyAllowlist | Deny payment to any counterparty not on the list | deny | guardrails.deny.counterparty_not_allowlisted | | businessHoursOnly | Block (or escalate) spend outside business hours in an IANA timezone | deny or require_approval | guardrails.deny.outside_business_hours | | velocityCountCap | Circuit breaker on transfer count per window (catches runaway retry loops) | require_approval or deny | guardrails.pending.velocity_count_exceeded |

Every preset accepts mode: "shadow" to observe before enforcing.

Graduated autonomy

The intended adoption path, and the one the hosted platform is built around:

  1. Shadow. Ship every policy with mode: "shadow". Decisions stay allow, but the reason trail records what would have happened (guardrails.deny.shadow_mode_forced in summary_code). Watch it for a billing cycle.
  2. Enforce with a human lane. Flip to enforcing with require_approval effects. Agents keep working; the risky tail waits for a person.
  3. Widen autonomy. As an agent earns trust, raise its caps and convert approval lanes to allows. Tighten instantly by editing a policy; no agent redeploys.

Determinism and replay

Every decision is a pure function of (intent, policies, history, timestamp). The result's fingerprint is a SHA-256 over the canonical-JSON form of the intent (sorted keys at every level, integer-string amounts, no floats), computed with node:crypto. Store the inputs alongside fingerprint and decision_id and you have an audit log you can replay against any future version of the engine to detect drift.

If you want that as a service (a tamper-evident evidence ledger, approvals inbox, multi-rail ingestion, decision replay across policy versions, SOC 2 export), that is Axiru's hosted platform, which runs this exact evaluator. The OSS package is complete without it.

Relationship to protocol-level controls

| Layer | Example | Question answered | | --- | --- | --- | | Key / wallet | Per-key spending limits, MPC policy engines | Can this key sign this transaction? | | Protocol | x402 payment extensions, facilitator limits | Is this payment well-formed for this rail? | | Org (this package) | agent-spend-guardrails | Is this spend consistent with our rules, across all rails, with a replayable audit trail? |

Run all three. Protocol controls cannot see cross-rail velocity or org-wide counterparty policy; org controls cannot stop a leaked key. They compose.

Spec

The policy document format, rule semantics, precedence ladder, and reason-code namespaces are specified in the Agent Spend Policy Spec v0.2 (draft), published July 2026 under Apache-2.0 and derived from the production engine. Conforming implementations exist in TypeScript (this package and the hosted engine); the spec includes a conformance checklist for independent implementations.

Related packages

License

Apache-2.0. Copyright 2026 Axiru. See LICENSE.