CRE INTEGRATION
Add structural sensing to your Chainlink CRE workflow.
Hybrid · Q3-Q4 2026 · Integration guide
Since EIP-4844 (Dencun, March 2024), L1 basefee decoupled from L2 activity. Sequencer outages, bridge posting gaps and structural anomalies produce no economic signature on L1. Fee monitors are 100% blind to them. Every cross-chain agent operating today has no native observability of the substrate it executes on.
Every agentic system has an execution layer that orchestrates, calls and coordinates. No agentic system today has a layer that observes the structural state of the blockchain substrate it acts on.
| Concern | Execution layer | Sensing layer: Invarians |
|---|---|---|
| Role | Orchestrate, call, coordinate | Observe structural substrate state |
| What it knows | What to do, when, how | What the infrastructure is doing right now |
| Blind spot | Sequencer degradation, bridge stress, structural regime shifts | None: that is exactly what it measures |
| Signal type | Transaction status, gas price, confirmations | Signed regime attestation: L1 × L2 × Bridge |
| Examples | Chainlink CRE, intent solvers, keepers, RWA automation | Invarians: live, calibrated, signed |
Invarians classifies the blockchain infrastructure state across two independent axes: τ (structural rhythm) and π (demand pressure). Each combination maps to an execution context with distinct implications for AI agents. Since 2026-04-29, chains with calibrated lower bounds also emit signed direction codes: D2+ (elevated), D2- (depressed), D2± (composition asymmetric, agentic concentration), and S2+ / S2- on rhythm. Total: 12 codes on L1, 9 on L2. The 4 base codes below remain valid as aliases. See foundations §03b for the full signed grid.
Every call to Invarians returns a cryptographically signed snapshot of the current execution context: regime, freshness, and lineage. The agent applies its own policy. Invarians observes infrastructure state and signs it. Nothing more.
"version": "1.0.0",
"oracle_status": "OK",
"issued_at": "2026-04-20T14:22:01Z",
"panel": {
"l1": [{ "chain": "ethereum", "regime": "S1D1", "status": "OK", "window": "1h" }],
"l2": [{ "chain": "arbitrum", "regime": "S1D2", "status": "OK" }],
"bridges": [{ "id": "arbitrum-ethereum/cctp", "type": "cctp", "state": "BS1",
"calibrated": true, "status": "OK", "window": "10m" }]
},
"signed_execution_context": {
"payload_hash": "0x...",
"signature": "hmac-sha256:...",
"key_id": "invarians-v1",
"anchor": null
}
Cryptographically signed. HMAC-SHA256 attestation on every response. Ed25519 signatures across the internal collection pipeline. Independently verifiable via
POST /v2/verify.Agent-owned policy. Invarians publishes infrastructure state. The agent applies its own execution policy. There is no execution window, no recommendation, no prescription embedded in the signal.
Invarians is not built for one platform. Any system that executes autonomously on blockchain infrastructure gains observability by integrating the sensing layer.
The integration is a single HTTP call inserted between your trigger and your execution logic. Your workflow asks Invarians for the current regime: then decides based on that.
runInNodeMode with mode aggregation ensures all DON nodes reach BFT consensus on the regime value before your callback uses it.
Drop this pattern into any existing CRE workflow. The sensing call adds one HTTP request per trigger fire: negligible overhead, complete infrastructure observability.
// ── my-workflow/main.ts ──────────────────────────────────────────────
import {
CronCapability, HTTPClient, handler,
consensusStringModeAggregation, Runner,
type NodeRuntime, type Runtime
} from "@chainlink/cre-sdk"
// ── Config (from config.staging.json) ──────────────────────────────
type Config = {
schedule: string
inVariansApiKey: string // your inv_* API key
targetL1: string // "ethereum"
targetL2: string // "arbitrum" | "base" | "optimism"
}
// ── Invarians response type ─────────────────────────────────────────
type InVariansContext = {
oracle_status: "OK" | "DEGRADED"
l1Regime: "S1D1" | "S1D2" | "S2D1" | "S2D2" | null // from panel.l1[].regime, null when panel entry missing
l2Regime: string // from panel.l2[].regime
bridgeState: "BS1" | "BS2" | null // from panel.bridges[].state, null when not yet calibrated
}
// ── Step 1: Fetch Invarians context (runs on every DON node) ────────
const fetchInVariansContext = (
nodeRuntime: NodeRuntime<Config>
): InVariansContext => {
const http = new HTTPClient()
const l1 = nodeRuntime.config.targetL1
const l2 = nodeRuntime.config.targetL2
const resp = http.sendRequest(nodeRuntime, {
url: `https://api.invarians.com/v2/panel`,
method: "GET" as const,
headers: {
"Authorization": `Bearer ${nodeRuntime.config.inVariansApiKey}`,
}
}).result()
const panel = JSON.parse(
new TextDecoder().decode(resp.body)
)
const l1Entry = panel.panel.l1.find((e: any) => e.chain === l1)
const l2Entry = panel.panel.l2.find((e: any) => e.chain === l2)
const bridgeId = `${l2}-${l1}/cctp`
const bridgeEntry = panel.panel.bridges.find((b: any) => b.id === bridgeId)
return {
oracle_status: panel.oracle_status,
l1Regime: l1Entry?.regime ?? null,
l2Regime: l2Entry?.regime ?? "N/A",
bridgeState: bridgeEntry?.state ?? null,
}
}
// ── Step 2: Main callback ────────────────────────────────────────────
const onTrigger = (runtime: Runtime<Config>): string => {
// Query Invarians: BFT consensus across DON nodes on regime string
const ctx = runtime.runInNodeMode(
fetchInVariansContext,
consensusStringModeAggregation() // mode = most common value across nodes
)().result()
runtime.log(`Invarians: ${ctx.oracle_status}: L1:${ctx.l1Regime} L2:${ctx.l2Regime} Bridge:${ctx.bridgeState}`)
// ── Gate 1: Attestation freshness ────────────────────────────────
if (ctx.oracle_status !== "OK") {
runtime.log("Attestation STALE: deferring execution")
return "deferred:oracle_stale"
}
// ── Gate 2: L1 structural stress ─────────────────────────────────
if (ctx.l1Regime === "S2D1" || ctx.l1Regime === "S2D2") {
runtime.log(`Structural stress detected (${ctx.l1Regime}): deferring`)
return `deferred:structural_stress:${ctx.l1Regime}`
}
// ── Gate 3: Bridge state (cross-chain workflows) ──────────────────
if (ctx.bridgeState === "BS2") {
runtime.log("Bridge degraded: deferring cross-chain execution")
return "deferred:bridge_degraded"
}
// ── Infrastructure nominal: proceed ──────────────────────────────
runtime.log(`Nominal (${ctx.l1Regime}): executing`)
// ... your business logic here (onchain write, CCIP, computation)
return `executed:${ctx.l1Regime}`
}
// ── Workflow entry point ─────────────────────────────────────────────
const initWorkflow = (config: Config) => {
const cron = new CronCapability()
return [handler(cron.trigger({ schedule: config.schedule }), onTrigger)]
}
export async function main() {
const runner = await Runner.newRunner<Config>()
await runner.run(initWorkflow)
}
// config.staging.json
{
"schedule": "*/30 * * * * *",
"inVariansApiKey": "inv_your_key_here",
"targetL1": "ethereum",
"targetL2": "arbitrum"
}
Each gate handles a distinct failure mode. None of these are visible to fee monitors or accessible without a dedicated sensing layer.
| Check | Failure mode | What it means |
|---|---|---|
| oracle_status !== "OK" | Attestation freshness | Per-item freshness: L1/L2 stale beyond 1h, bridges beyond 10m. Any STALE or UNAVAILABLE item flips the global oracle_status to DEGRADED. Executing on stale context is executing blind: defer and retry at the next trigger fire. |
| panel.l1[].regime === "S2D1" or "S2D2" | Structural stress | S2 means infrastructure rhythm has deviated from baseline. This is the invisible regime: no fee signature, no gas spike. Detected only by Invarians τ axis measurement. |
| panel.bridges[].state === "BS2" | Bridge degraded | BS2 signals abnormal latency on the variable-latency bridge surface. For cross-chain workflows, this means the bridge is not operating at normal cadence. Both CCTP and CCIP are captured per message (capability_level: per_message_attested); CCTP carries the Circle ECDSA signature per message, CCIP matches source send and destination execute by bytes32 messageId. |
| 01 |
Set up Chainlink CRE
Follow the official getting started guide at docs.chain.link/cre. CRE is currently in Early Access: request access from Chainlink directly.
|
| 02 |
Get your Invarians API key
Sign up at invarians.com: free tier available (20 req/day for testing). Your key starts with
inv_. |
| 03 |
Add the sensing pattern to your workflow
Copy the TypeScript workflow above into your project's
main.ts. Add your Invarians API key and target chain to config.staging.json. |
| 04 |
Test and deploy
Simulate locally: verify the Invarians regime appears in your workflow logs. Deploy following the CRE documentation.
|
API documentation → · CRE docs →