DevelopersDOCS
CHAINSAGE · RISK API + AGENT SDK

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

DOCS

HTTP 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 }.

/api/v1/score

Full wallet report — healthScore, verdict, flags[], stats. Guardian's exact scan path.

/api/v1/classify

Risk classification for a single spender from on-chain reads.

/api/v1/simulate

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

DOCS

The 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 */ }
}
The fail-safe guarantee

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.