cookbook · vertical · web3-address-screener
Recipe · vertical

Wallets in, risk band + cited tx out.

A local .kolm file that takes an EVM address + 90 days of tx history and returns (risk_band, reasons[], cited_tx_hashes[], action). Reasons must trace to a sanctioned-list source or a tx hash present in the input. Trained on 2,000 labeled wallets from Chainalysis-equivalent and OFAC SDN data. On-prem.

base modelqwen2.5-coder-3b
gold pairs2,000 (1.4k train / 600 eval)
k-score floor0.88
artifact size1.6 GB
compile time~46 min
spec sourcegrounded + asymmetric cost

What this recipe does

A compliance team needs two things: a number that won't make the regulator unhappy, and an audit trail. This recipe gives both. The model returns a risk band; every reason cites either a sanctioned-list entry or a transaction hash in the input. Hallucinated risk reasons are blocked at the verifier — if the artifact says "interacted with Tornado Cash," there must be a tx in the input pointing at a Tornado contract.

Cost is asymmetric: a missed match against an OFAC SDN address is a regulatory event; a false flag is a 5-minute review. False-negative weight is 50× false-positive weight in the K-score loss. Compiled on-prem because the gold corpus contains licensed Chainalysis-equivalent labels.

The spec

{
  "output_kind": "json",
  "schema": {
    "required": ["risk_band", "reasons", "action"],
    "properties": {
      "risk_band": { "enum": ["clean", "watch", "high", "sanctioned"] },
      "reasons": { "type": "array", "items": {
        "required": ["reason", "evidence_tx"],
        "properties": {
          "reason": { "$ref": "reasons.json" },
          "evidence_tx": { "type": "array", "items": {"type":"string"} },
          "sdn_match": { "type": ["string", "null"] }
        }
      } },
      "action": { "enum": ["allow", "review", "block"] }
    }
  },
  "verifier": {
    "reason_must_be_in_taxonomy": true,
    "evidence_tx_must_appear_in_input": true,
    "sdn_match_must_resolve_to_sdn_list": true,
    "false_negative_cost": 50,
    "sanctioned_band_requires_sdn_match": true
  }
}

Compile (in your VPC, against your SDN snapshot)

kolm compile "AML address screener with cited tx evidence" \
  --base qwen2.5-coder-3b \
  --pairs ./labeled-wallets/*.jsonl \
  --taxonomy ./reasons.json \
  --sdn-list ./ofac-sdn-2026-05-09.json \
  --asymmetric-loss false-neg=50 \
  --verifier evidence-grounded,sdn-resolves \
  --k-floor 0.88 \
  --output web3-screener.kolm

ok wrote web3-screener.kolm
   k_score=0.92  signature=hmac-sha256
   sdn-match recall 100% on synthetic adversarial (n=240)

K-score gate

K-score 0.92 held-out 600 wallets · sanctioned-recall 100% · high-risk recall 96% · precision-at-block 94% · evidence-grounded 100%

Run-time profile

Mac Studio
740ms
RTX 5090
200ms
Hospital server
2.1s
CPU x86
2.8s

Deploy

// pre-trade gate — every withdrawal address checked before approval:
on_withdrawal_request = async (req) => {
  const txs = await chain.txHistory(req.address, { days: 90 });
  const r = kolm.run('web3-screener.kolm', { address: req.address, txs });
  audit.log({ withdrawal: req.id, screener_receipt: r.receipt });
  if (r.action === 'block') return reject(req, r.reasons);
  if (r.action === 'review') return queue.compliance(req, r);
  return approve(req);
};