Get a verdict before your agent signs.
Two ways to call the same engine that powers Guardian: an HTTP Risk API for any stack, and a TypeScript Agent SDK for agents that sign. Both return one verdict — ALLOW · REVIEW · DENY — grounded in live Base reads.
Honest status: the engine and both interfaces are real and tested. There is not yet a hosted, managed API with issued keys — today you run the Risk API from the risk-apiworkspace (auth & rate-limit are documented stubs), and the SDK runs in local mode against your own RPC. A managed endpoint and key issuance are building.
Risk API
DOCSHTTP verdicts for any language. All endpoints are POST, versioned under /api/v1, authenticated with an x-api-key header, and return the envelope { ok, data | error }.
Full wallet report — healthScore, verdict, flags[], stats. Guardian's exact scan path.
Risk classification for a single spender from on-chain reads.
Pre-sign verdict for an approve/transfer intent, with an explicit notChecked[].
Example — score a wallet
curl -s https://your-host/api/v1/score \
-H "x-api-key: demo" \
-H "content-type: application/json" \
-d '{ "address": "0xYourWallet" }'
# → { "ok": true, "data": { "report": { "healthScore": 82,
# "verdict": "REVIEW", "flags": [ ... ], "stats": { ... } } } }The public demo key and the in-memory rate-limiter are deliberate stubs for local use; Redis/Upstash and a real key store are the production upgrades (documented in the risk-api README).
Agent SDK
DOCSThe chainsage npm package. One call returns a verdict; it fails safe — a network error or timeout never yields a silent ALLOW.
Install
npm install chainsage viem
check() — ask for a verdict
import { ChainSage } from "chainsage";
const cs = new ChainSage(); // local mode by default
const verdict = await cs.check({
kind: "approve",
chain: "base",
token: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
spender: "0x…",
amount: "unlimited",
owner: "0x…",
});
verdict.decision; // "ALLOW" | "REVIEW" | "DENY"
verdict.score; // 0–100, always inside the band for decision
verdict.reasons; // why — each maps to a real check
verdict.notChecked; // what was NOT verified (no fabricated checks)guard() — only execute on ALLOW
import { ChainSage, ChainSageDenied, ChainSageReview } from "chainsage";
const cs = new ChainSage();
try {
await cs.guard(intent, () => wallet.signAndSend(tx)); // runs ONLY if ALLOW
} catch (e) {
if (e instanceof ChainSageDenied) { /* blocked — verdict on e.verdict */ }
if (e instanceof ChainSageReview) { /* held for a human */ }
}A trust layer that fails open is worse than none. check() never returns ALLOW when it could not actually compute a verdict — any read failure or timeout produces a non-ALLOW failSafe verdict (default REVIEW, or DENY to fail-closed). This is enforced by a mandatory test that injects a throwing fetch.