Agent Guide
Observing many signals. Resolving one view.
How to consume the Demos Network Oracle as a machine agent.
Purpose
The Oracle provides current network state for the Demos blockchain testnet. It is strictly watch-only: it observes, interprets, and publishes. It does not advise, predict, or issue instructions.
Your agent reads the state and decides what to do with it. The Oracle never tells you.
Endpoint
GET /organism
Returns 17 top-level JSON fields. No fleet data. Every top-level field is always present and never null. Most fields are flat values; risk_factors is an array of strings and last_24h is a small summary object (fields inside it may be null while history accumulates). Refreshes every 20 seconds.
Machine-readable contract: /organism/schema — JSON Schema with stability guarantees (additive-only within api_version 1.x) and changelog. Validate your integration against it.
{
"status": "unknown",
"trend": "unknown",
"risk": "elevated",
"data_quality": "insufficient",
"confidence": "uncertain",
"agreement": "unknown",
"active_incidents": 0,
"max_incident_severity": "none",
"summary": "Insufficient data — fewer than 2 public nodes reachable",
"status_reason": "Insufficient data to assess network state",
"risk_factors": [
"Only 1 of 5 public nodes reachable — limited cross-checking"
],
"confidence_reason": "Insufficient reachable public nodes to cross-check",
"agreement_reason": "Fewer than 2 reachable nodes",
"staleness_seconds": 1,
"last_updated": "2026-06-10T08:28:38.773Z",
"api_version": "1.0",
"last_24h": {
"sufficient": true,
"coverage_pct": 99.9,
"observed_cycles": 4317,
"expected_cycles": 4320,
"typical_set_size": 5,
"peak_set": null,
"chain_movement": { "state": "unknown", "reason": "no_data" },
"longest_non_stable_minutes": 0,
"active_critical_public_incidents": 0,
"computed_at": "2026-06-10T08:28:38.773Z"
}
}
This is a real captured response. Note the honest-uncertainty values (unknown, insufficient, uncertain) — your parser must treat these as first-class states, not errors.
Field Meanings
status — network operability. stable degraded unstable unknown
risk — resilience / safety margin. low elevated high
confidence — certainty of assessment. clear uncertain
data_quality — observability. sufficient insufficient
agreement — validator consensus. strong moderate weak unknown
trend — direction of change. improving stable worsening unknown
active_incidents — count of current unresolved issues.
max_incident_severity — worst active incident: none info warning critical
staleness_seconds — seconds since last observation. Use for freshness judgment.
status_reason — one-sentence explanation of the current status.
risk_factors — array of strings; the concrete observations behind the current risk level.
confidence_reason — why confidence is at its current state.
agreement_reason — why agreement is at its current state.
last_24h — rolling 24-hour observability summary (coverage, observed vs expected cycles, chain movement, incident counts). Fields inside it may be null while history accumulates.
The Minimal Triple
The simplest consumption pattern reads three fields:
status + risk + confidence
These give you the complete picture in three values. Add data_quality for trust calibration and active_incidents for problem awareness.
Interpretation: network is operational, but redundancy is reduced.
Trust Calibration
Before relying on the assessment, check:
data_quality — if insufficient, treat all values with skepticism.
staleness_seconds — if high, data may not reflect current reality.
confidence — if uncertain, signals conflict. Consume with caution.
data_quality is insufficient, status will be unknown and risk will be elevated. This is intentional — the Oracle treats missing data as a reason for caution.Polling Guidance
Recommended interval: 10–30 seconds. The Oracle updates every 20 seconds.
Respect the Cache-Control: public, max-age=5 header. Do not poll faster than every 5 seconds.
For less time-sensitive consumers, polling every 60 seconds is sufficient.
Consumption Examples
curl
curl -s https://demos-oracle.com/organism | jq '{status, risk, confidence}'
JavaScript
const res = await fetch('https://demos-oracle.com/organism');
const state = await res.json();
if (state.status === 'unstable' || state.risk === 'high') {
// handle degraded network
}
Python
import requests
state = requests.get('https://demos-oracle.com/organism').json()
if state['data_quality'] == 'insufficient':
pass # data unreliable, act cautiously
Other Endpoints
/health — full diagnostic with agreement details, public nodes, signals, reference data.
/incidents — incident log. Default scope: public. Use ?scope=all for fleet.
/commerce/observations — commerce infrastructure reachability (Layer 2, independent from the core network assessment).
/methodology — how the Oracle makes assessments.
/commerce/methodology — how commerce observation works.
Error Handling
The Oracle is designed to always return valid JSON with all fields present. However, your agent should handle network and edge-case failures gracefully.
HTTP errors — The Oracle may return 502/503 during restarts (typically <30 seconds). Retry with exponential backoff.
Stale data — If staleness_seconds exceeds 120, the Oracle may be restarting or experiencing issues. The data is still valid but may not reflect the current moment. Your agent should flag this.
Insufficient data quality — When data_quality is insufficient, the Oracle cannot see enough public nodes to form a credible assessment. All other fields are still present but should be treated as low-confidence. Status will be unknown and risk will be elevated.
Timeouts — Set a reasonable timeout (5–10 seconds). If the Oracle doesn't respond, your agent should fall back to its last known state or a safe default, not crash.
Edge Cases
These state combinations are real and your agent should handle them explicitly:
status: stable + risk: elevated
The network is working, but resilience is reduced. Fewer nodes than ideal are reachable. The chain functions, but a single additional failure could cause degradation. Your agent should continue operating but with heightened caution.
status: unknown + data_quality: insufficient
The Oracle cannot see enough public nodes to assess the network. This is not "the network is down" — it is "the Oracle cannot tell." Your agent should not assume the worst. It should wait and retry, or fall back to the last known good state.
status: stable + confidence: uncertain
The Oracle has visibility but the signals are contradictory. Nodes may report different block heights or mixed health. The assessment says "stable" but with reduced certainty. Your agent should consume this data but flag it for human review.
agreement: unknown
Fewer than 2 public nodes are reachable, so consensus cannot be measured. This often accompanies data_quality: insufficient. It does not mean validators disagree — it means the Oracle cannot observe enough to tell.
trend: unknown
Not enough recent history to compute a trend. Common after Oracle restarts or data gaps. Trend resets to unknown until enough consecutive observations accumulate. This is normal, not an error.
staleness_seconds > 60
The Oracle's last observation is more than a minute old. Possible causes: Oracle restarting, high load, network issues between the Oracle and its data sources. The data is still the best available — it's just not fresh. Your agent should note this and poll again shortly.
Production Python Example
import requests
import time
import logging
ORACLE_URL = "https://demos-oracle.com/organism"
MAX_STALENESS = 120 # seconds
POLL_INTERVAL = 20 # seconds
MAX_RETRIES = 3
logger = logging.getLogger("oracle_consumer")
def fetch_oracle_state():
# Fetch and validate Oracle state with error handling
for attempt in range(MAX_RETRIES):
try:
r = requests.get(ORACLE_URL, timeout=10)
r.raise_for_status()
state = r.json()
# Validate required fields exist
required = ["status", "risk", "confidence",
"data_quality", "staleness_seconds"]
for field in required:
if field not in state:
logger.warning(f"Missing field: {field}")
return None
return state
except requests.exceptions.Timeout:
logger.warning(f"Oracle timeout (attempt {attempt + 1})")
time.sleep(2 ** attempt)
except requests.exceptions.HTTPError as e:
logger.warning(f"Oracle HTTP {e.response.status_code}")
if e.response.status_code in (502, 503):
time.sleep(5) # Oracle restarting
else:
return None
except Exception as e:
logger.error(f"Oracle error: {e}")
return None
return None # All retries exhausted
def assess_reliability(state):
# Determine if the Oracle data is reliable enough to act on
if state is None:
return {"reliable": False, "reason": "Oracle unreachable"}
if state["data_quality"] == "insufficient":
return {"reliable": False,
"reason": "Oracle has limited visibility"}
if state["staleness_seconds"] > MAX_STALENESS:
return {"reliable": False,
"reason": f"Data is {state['staleness_seconds']}s old"}
if state["confidence"] == "uncertain":
return {"reliable": True, # usable but flagged
"reason": "Signals conflict — use with caution",
"flagged": True}
return {"reliable": True, "reason": None}
# Usage
state = fetch_oracle_state()
check = assess_reliability(state)
if check["reliable"]:
# Safe to use state["status"], state["risk"], etc.
pass
else:
logger.info(f"Oracle data unreliable: {check['reason']}")
# Fall back to last known state or safe default
Combining Endpoints
For richer context, combine multiple Oracle endpoints:
# Minimal: just the state GET /organism # Detailed: state + diagnostic data GET /organism → status, risk, confidence GET /health → agreement details, node counts, signals GET /incidents → specific active problems # Commerce: attestation authority reachability GET /commerce/observations → authority states (Layer 2, separate from the core network assessment)
Important: /commerce/observations is Layer 2 data. It reports whether attestation authority endpoints are reachable. It does not influence and is not influenced by the network assessment in /organism. These are independent observation layers.
Commerce API (Layer 2)
The Oracle also monitors attestation authority endpoints used by the Demos agent commerce protocol. This is a separate observation layer.
GET /commerce/observations
{
"layer": "commerce_intelligence",
"network_context": "testnet",
"commerce_observability_state": "healthy",
"authorities_observed": 10,
"authorities_healthy": 10,
"authorities": [
{
"authority_id": "gleif",
"name": "GLEIF",
"category": "public_api",
"reachability": "healthy",
"freshness": "fresh",
"observed_at": "2026-05-18T..."
}
]
}
commerce_observability_state — overall: healthy degraded partial unavailable unknown
reachability — per authority: healthy degraded unavailable unknown
/organism status, risk, trend, agreement, confidence, or data quality. These are architecturally independent observation layers.Full commerce methodology: /commerce/methodology
HTTP Status Codes
200 — Success. Valid JSON response.
301 — Redirect (e.g., /home → /).
401 — Unauthorized. Admin endpoints require ?token= parameter.
404 — Endpoint not found.
502/503 — Oracle restarting. Retry after 5–10 seconds.
Content-Type: application/json and Access-Control-Allow-Origin: * (CORS enabled).Design Principle
The Oracle publishes its core assessment. Your agent interprets it.
DNO informs context; it does not advise, predict, score, certify, or decide action.