Three-tier lookup

Every check() walks three tiers in order. Each tier answers the same question (do we already know this threat?) at progressively higher cost. The chain is the source of truth; the local cache is a performance shortcut on top of it; the CRE jury only fires when neither has seen the threat before.

┌────────────────────────────────────────────────────────────────┐
│  Tier 1, local cache                  ~1 ms                     │
│  in-memory matchers indexed by (chainId, address), selector,    │
│  bytecode hash, taint set, semantic marker                      │
│                                                                 │
│  miss ↓                                                         │
│                                                                 │
│  Tier 2, Base registry RPC            ~200 ms                   │
│  getAntibodyByMatcherHash(primaryMatcherHash) on Base           │
│  populates Tier 1 on hit so the next check resolves locally     │
│                                                                 │
│  miss ↓                                                         │
│                                                                 │
│  Tier 3, CRE jury                     seconds                   │
│  requestVerification on chain -> diverse-model CRE verdict      │
│  fires only for genuinely novel threats; can auto-publish the   │
│  resulting antibody so the next agent's Tier 1 catches it       │
└────────────────────────────────────────────────────────────────┘

Lookup finds a matching antibody. A separate read-side step then decides whether that match hard-blocks or only warns. See Two-speed enforcement.

Why three tiers

Without Tier 2, an agent with a cold cache re-detects threats the network has already minted, wasting CRE calls and fragmenting the corroboration signal across duplicate antibodies. Tier 2 makes the chain (not the cache) the canonical record: a cold-cache agent finds the existing antibody on chain and pulls it into its cache instead of re-deriving it.

What gets probed at each tier

Tier 1, local cache

Five matchers run cheap-first; first hit wins.

Matcher Hashed input Lookup shape
ADDRESS (chainId, target) Map<"chainId:address", Antibody>
CALL_PATTERN (chainId, target, selector, argsTemplate) Map<"chainId:target:selector:argsHash", Antibody>
GRAPH (chainId, sorted addresses) reverse Map<"chainId:address", Set<keccakId>>
BYTECODE keccak256(runtime bytecode) Map<bytecodeHash, Antibody>
SEMANTIC flavor + marker scan over markers

Tier 2, Base registry RPC

When Tier 1 misses, the SDK builds candidate primary-matcher hashes from the tx and context, then queries the Registry on Base for each one until it finds a hit (or exhausts the candidates). On a hit the antibody is decoded once and pushed into the local cache so the next check serves it locally.

A short-lived negative cache suppresses repeated RPC traffic for the same legitimate-but-uncommon counterparty. Entries carry a TTL, so a freshly minted threat becomes visible after at most that window even without a cache reset.

Tier 3, CRE jury

When the cache and the chain are both empty for a given input and novelThreatPolicy: "verify" is set, the SDK posts the distilled, ECIES-encrypted context to the chain via requestVerification (the agent's wallet pays the check fee) and awaits the Chainlink CRE jury's DON-attested verdict. On a confirmed threat, if you opted into autoPublishConfirmedThreats, the SDK publishes the synthesized antibody so subsequent agents catch the same threat at Tier 1 or 2.

trust-cache skips Tier 3 and allows the action with novel: true. deny-novel blocks unconditionally on a Tier 1 + Tier 2 miss. If no verifier is available, the verify path fails closed: a novel input is never silently allowed.

See Novel-threat verification for the full CRE attestation story and its limits.

Decision source

The source field on a returned CheckResult tells you which tier resolved:

value meaning
"cache" Tier 1 hit
"registry" Tier 2 hit (cache miss + chain hit)
"tee" Tier 3 hit (CRE verdict, possibly auto-published)
"policy" no tier hit; deny-novel or trust-cache decided

The novel flag is true only for "policy"-sourced allows under trust-cache.

Failure modes

  • RPC unavailable. The Tier-2 lookup swallows fetch errors and falls through to the policy fork. The SDK degrades to two-tier behavior; cache hits still work, novel threats still reach CRE under verify.
  • No verifier configured. Under verify, a missing verifier fails closed (the novel input is not silently allowed).
  • Stale negative cache. Entries expire on a TTL, so a freshly minted threat surfaces after at most one window.

See also