Python SDK for the Invarians panel API v2.0 — three primitives (Attestation + Regime + Shift) for cross-chain infrastructure context to autonomous agents
Project description
invarians-py
Cross-chain infrastructure context for autonomous agents. Three primitives in one signed payload: Attestation, Regime, Shift.
L2 activity no longer shows up in L1 gas fees. Sequencer slowdowns and bridge delays leave no economic trace. Fee monitors stay silent. Invarians detects them.
Since v0.7.0 (2026-05-04), the SDK targets the production endpoint at https://api.invarians.com and exposes the v2.0 panel: a single direction-agnostic payload with axis-grouped metric blocks, drift signals, and 12 signed regime codes per chain. Bridge classification scope is variable-latency surfaces only (Chainlink CCIP, Circle CCTP).
from invarians import InvariansClient
client = InvariansClient(api_key="inv_your_key_here")
panel = client.get_panel_v2(include="diagnostic")
eth = panel.l1_by_chain("ethereum")
arb = panel.l2_by_chain("arbitrum")
br = panel.bridge_by_id("arbitrum-ethereum/cctp")
# Regime: 12 signed codes (S1D1, S1D2+, S1D2-, S1D2±, S2+D1, S2-D1, S2+D2+, ...)
if eth.regime and (eth.regime.startswith("S2") or eth.regime.endswith("D2-")):
pause_agent_execution()
# Drift: per-axis composite trend, plus per-metric shift
if eth.drift.demand_magnitude_delta is not None and eth.drift.demand_magnitude_delta > 0:
log.info("Demand axis deviation amplifying on ethereum")
print(panel.oracle_status) # "OK" | "DEGRADED"
print(eth.regime, eth.status) # e.g. "S1D1" "OK"
print(br.state, br.calibrated) # e.g. "BS1" True (CCTP preliminary)
Install
pip install invarians[requests] # default
pip install invarians[httpx] # async-friendly
Requires Python 3.9+. Get an API key at invarians.com.
The three primitives
The v2.0 panel separates three independent concerns. Every panel response carries all three.
1. Attestation (HMAC integrity)
Every panel response carries a signed_execution_context with payload_hash, signature, key_id, and an optional on-chain anchor. Independently verifiable.
panel = client.get_panel_v2()
sec = panel.signed_execution_context
ok = client.verify_panel_v2(panel_raw_dict, sec.signature)
# True if HMAC matches the canonical JSON of the payload
2. Regime (12 signed codes per chain)
Per-chain regime is a 2-axis tuple on the SxDx grid. Structure axis: S1 nominal, S2+ structural high, S2- structural low. Demand axis: D1 nominal, D2+ demand high, D2- demand low, D2± composition split. Twelve codes total per chain on both L1 and L2.
eth = panel.l1_by_chain("ethereum")
if eth.regime == "S2+D1":
# Structural high stress, demand nominal
return {"action": "hold", "reason": eth.regime}
elif eth.regime and eth.regime.startswith("S1") and not eth.regime.endswith("D1"):
# Nominal infrastructure, asymmetric or elevated demand
proceed_with_caution()
3. Shift (drift signal)
Each metric block exposes ratio (current state vs short EMA), ratio_long (current vs long EMA), shift (deviation magnitude), shift_delta (raw direction), shift_magnitude_delta (deviation amplifying or shrinking). Plus a per-axis composite drift on every chain entry.
eth = panel.l1_by_chain("ethereum")
# Per-axis composite drift
print(eth.drift.demand) # composite drift magnitude on demand axis
print(eth.drift.demand_magnitude_delta) # > 0 amplifying, < 0 reverting
# Per-metric shift (diagnostic mode only)
print(eth.demand.tx.shift) # per-metric tx-count shift
print(eth.structural.rhythm.shift) # per-metric rhythm shift
Trend reading rule for an agent in an active regime:
shift_magnitude_delta |
Interpretation |
|---|---|
> 0 |
Deviation amplifying. Regime persists or worsens. |
< 0 |
Deviation shrinking. Regime exit toward nominal likely. |
≈ 0 |
Regime stable. |
Common patterns
Hold on structural stress
panel = client.get_panel_v2()
eth = panel.l1_by_chain("ethereum")
if eth.regime and eth.regime.startswith("S2"):
# Structural stress, regardless of polarity (S2+ or S2-)
return {"action": "hold", "reason": eth.regime}
Detect silent slowdown (no fee signal)
S2+D1 and S2-D1 are the codes where infrastructure degrades without any demand signature. Fee monitors stay silent.
eth = client.get_panel_v2().l1_by_chain("ethereum")
if eth.regime in ("S2+D1", "S2-D1"):
# No gas spike, no price move, but the chain is structurally stressed
alert_ops(f"Silent stress on ethereum: {eth.regime}")
Certify execution conditions on chain
panel = client.get_panel_v2()
sec = panel.signed_execution_context
if panel.oracle_status == "OK":
result = execute_trade(...)
audit_log.append({
"tx": result.hash,
"panel_version": panel.version, # "2.0.0"
"issued_at": panel.issued_at,
"payload_hash": sec.payload_hash, # "0x{sha256}"
"signature": sec.signature, # "hmac-sha256:{hex}"
"key_id": sec.key_id,
"anchor": sec.anchor, # on-chain anchor slot when available
})
Route around bridge stress
Bridge IDs are canonical: {chainA}-{chainB}/{type} with type ∈ {ccip, cctp}. Bridge classification scope is variable-latency surfaces only.
panel = client.get_panel_v2(bridges=["ccip", "cctp"])
# CCTP: preliminary calibration since 2026-05-04 (P97/14d on circle_api_latency_ms, confidence LOW)
br = panel.bridge_by_id("arbitrum-ethereum/cctp")
if br and br.calibrated and br.state == "BS2":
use_fallback_route()
# CCIP: state classification deferred until sustained throughput
# Raw signals exposed in the meantime
ccip = next((b for b in panel.bridges if b.type == "ccip"), None)
if ccip and ccip.commit_latency_p90_s and ccip.commit_latency_p90_s > 600:
log.warning(f"{ccip.id}: commit latency P90 {ccip.commit_latency_p90_s:.0f}s")
# RMN cursed override (CCIP only) — absolute binary, lane is frozen
if ccip and ccip.is_frozen:
block_ccip_route()
Handle degraded data gracefully
panel = client.get_panel_v2()
if panel.oracle_status == "DEGRADED":
for entry in panel.l1 + panel.l2:
if entry.status != "OK":
log.warning(f"{entry.chain}: {entry.status}")
for br in panel.bridges:
if br.status in ("STALE", "UNAVAILABLE"):
log.warning(f"{br.id}: {br.status}")
fall_back_to_conservative_mode()
Per-item status values:
| Status | Meaning |
|---|---|
OK |
Signal fresh and calibrated |
STALE |
Last update older than the freshness window (1h) |
UNAVAILABLE |
Signal temporarily missing |
UNCALIBRATED |
Collector running, thresholds not yet published. Does not trigger DEGRADED. |
Regime grid
12 signed codes per chain on both L1 and L2.
| Code | Structure | Demand | What it captures |
|---|---|---|---|
S1D1 |
nominal | nominal | Within calibrated norms |
S1D2+ |
nominal | high | Demand surge, infrastructure healthy |
S1D2- |
nominal | low | Demand depressed, infrastructure healthy |
S1D2± |
nominal | split | Asymmetric demand composition |
S2+D1 |
high stress | nominal | Silent structural slowdown. No fee signal. |
S2-D1 |
low stress | nominal | Silent structural underrun. No fee signal. |
S2+D2+ |
high stress | high | Combined upward stress |
S2+D2- |
high stress | low | Stress with depressed demand |
S2+D2± |
high stress | split | Stress with asymmetric demand |
S2-D2+ |
low stress | high | Underrun with elevated demand |
S2-D2- |
low stress | low | Underrun with depressed demand |
S2-D2± |
low stress | split | Underrun with asymmetric demand |
Bridge states (variable-latency surfaces only):
| Code | Type | Meaning |
|---|---|---|
BS1 |
ccip / cctp | Within calibrated latency threshold |
BS2 |
ccip / cctp | Above calibrated latency threshold |
null |
any | Not yet calibrated. Raw signals still exposed on the entry. |
Calibration status:
- CCTP: preliminary calibration since 2026-05-04 (P97/14d on
circle_api_latency_ms, confidence LOW). StateBS1/BS2populated. - CCIP: classification deferred until sustained throughput on
last_sequence_advance_seconds. Statenull. RMN cursed override remains absolute.
Chain coverage
| Chain | Layer | Confidence | Status |
|---|---|---|---|
| ethereum | L1 | HIGH | live |
| polygon | L1 | MEDIUM | live |
| arbitrum | L2 | MEDIUM | live |
| base | L2 | MEDIUM | live |
| optimism | L2 | MEDIUM | live |
| avalanche | L1 | LOW | observation |
| solana | L1 | LOW | calibration target Q3 2026 |
Bridges live (variable-latency scope, 20 lanes total): 10 CCIP lanes (raw signals exposed, classification deferred until sustained throughput) and 10 CCTP routes (preliminary BS1 / BS2 calibration since 2026-05-04, confidence LOW, on circle_api_latency_ms).
Migrating from v0.6.x
v0.7.0 narrows the bridge scope to variable-latency surfaces (CCIP, CCTP). Native L2-to-L1 bridges operate on protocol-defined timeframes outside any observability lever and are removed from the panel. Several types and fields are removed accordingly.
# Removed types
# from invarians import CcipState, CctpState, AnyBridgeState # gone — use BridgeState
# Removed fields on BridgeEntry
# br.last_batch_age_seconds # gone (native-only signal)
# Removed fields on Coverage / V2Coverage
# coverage.bridges_native # gone
# BridgeType is now Literal["ccip", "cctp"] (was: "native" | "ccip" | "cctp")
# State codes CS1 / CS2 (CCIP) and TS1 / TS2 (CCTP) are unified as BS1 / BS2
If you previously did bridge_by_id("arbitrum-ethereum/native"), switch to a CCTP route ("...-ethereum/cctp") or a CCIP lane ("...-ethereum/ccip").
Error handling
from invarians.exceptions import AuthError, RateLimitError, ServerError
try:
panel = client.get_panel_v2()
except AuthError:
print("Invalid API key")
except RateLimitError:
print("Quota exceeded. Free tier: 20 req/day")
except ServerError as e:
print(f"Service unavailable: {e}")
Documentation
API reference: invarians.com/developers.html
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file invarians-0.7.0.tar.gz.
File metadata
- Download URL: invarians-0.7.0.tar.gz
- Upload date:
- Size: 22.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6dd007241f7b92490fe46cd26cdb1702829bf2072d7e1e5dcfe07b6f1902aec
|
|
| MD5 |
b757b00022ebc4311f9bc2b1cd9ef291
|
|
| BLAKE2b-256 |
e67723df0b28bb892abf3d47cecb7f9b188d90b98ba50dbefce61f46fe77ec43
|
File details
Details for the file invarians-0.7.0-py3-none-any.whl.
File metadata
- Download URL: invarians-0.7.0-py3-none-any.whl
- Upload date:
- Size: 19.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
86711adedcc84f120c08cde015f8b3d768f7f012c2e064c8a30776c052653010
|
|
| MD5 |
e99728d3eb72ca4c4db45ce8578b4129
|
|
| BLAKE2b-256 |
75a2c21901336100c4245a3aa39f4ef6af0113c2a317d4919d72b6dd0764726d
|