"Just trust the JSON" is how most agent stacks treat the physical world. Temperature arrives. PM2.5 arrives. The agent bills, ships, decides. Nobody asks whether the sensor was stuck, spiked, or inventing a sky that never happened.
We already had two ways to ground an answer in the AI-Factory / AIMarket ecosystem:
| Class | What it proves | How you check it |
|---|---|---|
| Math oracles | a computation | re-verify the proof, byte-for-byte |
| Metis | an LLM delivery vs buyer intent | council → verifier → verify_score
|
| GAIA (new) | a reading from the world | physics bounds + history + co-located twin + Ed25519 device attestation |
GAIA is the third class: a physical-world oracle gateway. Agents buy Ed25519-attested sensor readings as normal AIMarket capabilities. Settlement uses the same Pay-on-Verified escrow we already ship for LLM work — except the judge is not a language model. It is a sub-millisecond plausibility verifier that speaks Metis's /v1/verify envelope.
Honest reading → provider gets paid.
Lying / stuck / drifted sensor → buyer refunded automatically.
Unreachable device → no debit at all.
Live demo (no login): iot.modelmarket.dev · Source: github.com/alexar76/gaia (MIT)
The problem nobody budgets for
Agent A needs "current outdoor temp at site X" to decide whether to delay a delivery, adjust a quote, or trigger a physical workflow. Today the happy path is:
- Call some weather API or IoT bridge
- Parse
temperature_c - Act (and often pay) as if the number is true
That works until it doesn't. Sensors fail in boring, expensive ways:
- Stuck — ADC latch-up; six identical values to four decimals
- Spike — EMI / loose wire; 12°C → 87°C between samples
- Drift — slow miscalibration that never trips a z-score alone
- Dropout — radio dead; callers retry into empty air and still get billed by naive bridges
If your agent economy debits on response, not correctness, a lying sensor is a profitable attack surface. You don't need fancy crypto drama for that — you need escrow that understands physics.
What GAIA actually sells
Not a dashboard. Not a "digital twin theatre." Paid capabilities on the AIMarket v2 wire:
| Capability | Price (demo) | What you get |
|---|---|---|
gaia.weather.read@v1 |
$0.001 | T / RH / P / wind + device attestation |
gaia.air.read@v1 |
$0.001 | PM2.5 / PM10 / CO₂ / VOC + attestation |
gaia.energy.read@v1 |
$0.001 | V / A / W + monotonic Wh register |
gaia.window@v1 |
$0.05 | N readings in one invoke (clears ledger quantum) |
gaia.verify@v1 |
— | statistical plausibility verdict |
gaia.fleet.status@v1 |
free | fleet registry + pinned device pubs |
Demo fleet: two weather stations (ws-01, ws-02) sharing one site truth — the twin is required for sibling checks — plus air quality and energy. Models imitate BME280 / SDS011 / SCD30 / Shelly-EM-class hardware.
Honest caveat up front: the public demo fleet is simulated. Every wire surface is real — manifest, invoke, receipts, provider signature, verify envelope, W3C WoT Thing Descriptions. Live public sensors (NOAA / OpenSenseMap / OGC SensorThings) ride the same attestation + verifier path in gaia/devices/live.py. Unreachable upstream → 503 → no debit.
Thirty seconds to a signed reading
curl -s https://iot.modelmarket.dev/ai-market/v2/manifest | jq '.capabilities_count'
# → 6
curl -s -X POST https://iot.modelmarket.dev/ai-market/v2/invoke \
-H 'Content-Type: application/json' \
-d '{
"capability_id": "gaia.weather.read@v1",
"product_id": "gaia.gateway",
"input": { "device_id": "ws-01" }
}'
You get back something like:
{
"ok": true,
"output": {
"reading": {
"device_id": "ws-01",
"model": "GAIA-WS1 (BME280-class + anemometer)",
"site": "demo-site-1",
"seq": 1,
"ts": "2026-07-29T20:55:24Z",
"values": {
"temperature_c": 12.2365,
"humidity_pct": 66.3611,
"pressure_hpa": 1013.8333,
"wind_mps": 3.108
}
},
"attestation": {
"algorithm": "ed25519",
"public_key": "ndZPK7zIWdK+xFQMDOfPCaCValSOWrpCzs/DmzHN4C0=",
"value": "…",
"canonical": "device|model|seq|ts|values_sha256"
}
},
"price_usd": 0.001,
"receipt": { "nonce": "…", "signature": { "algorithm": "ed25519", "value": "…" } }
}
Three signatures, three claims:
-
Device → reading — per-device Ed25519 over
device|model|seq|ts|values_sha256 -
Gateway → response — request-bound
X-Provider-Signature(input hash included) - Hub → settlement — verification envelope signed after the verdict
On real hardware the device key moves into a secure element / TEE — the slot the AIMarket protocol already reserves. Plausible numbers from an unproven sensor are worth nothing; identity is layered under the statistics.
Pay-on-Verified, but the judge is physics
Pay-on-Verified is buyer-opt-in escrow on the hub: hold funds, return the provider output immediately, move money only after a machine verdict.
For LLM work the judge is Metis.
For sensors the judge is GAIA's /v1/verify — same envelope shape, so the hub does not care which one is plugged in:
export AIMARKET_VERIFY_METIS_URL=http://gaia-host:9320
export AIMARKET_VERIFY_VERIFIER_ID=gaia.verify@v1
End-to-end:
- Buyer invokes
gaia.weather.read@v1with averifyblock (intent + wait policy) - Hub calls GAIA → attested reading returned
- Hub holds the channel funds (does not debit yet)
- Settlement worker
POSTs GAIA/v1/verifywith the audit string -
Pass → capture hold,
verify_passedreputation event -
Fail → release hold, signed rejection receipt with
trace_id: gaia_…,verify_failed - Dropout / 5xx → no hold, no debit
Guaranteed in-process by gaia/tests/test_hub_e2e.py: honest → capture at the 1¢ ledger quantum; spiked → output delivered but hold released; dropout → 502 and an untouched balance.
That is the product thesis in one line: agents pay for weather that happened, not weather that was imagined.
How a sensor gets convicted (no LLM)
The plausibility verifier is deterministic. Identity first (unknown device or bad attestation → score 0.0). Then every field independently. Then MIN over fields — not mean — because a sensor lies one channel at a time, and averaging would let three honest fields launder one fabricated one.
Hard checks (physics, not vibes):
- bounds within
[lo, hi] - monotonic energy register never decreases
- stuck: 6 identical values on a continuous field
- schema: known field, numeric value
Soft checks (statistics that know when to abstain):
- z-score vs own history (≥ 24 samples; skip bursty fields like
wind_mps/power_w) - rate vs jitter + slope × Δt
- sibling agreement with the co-located twin (fresh ≤ 10 min)
Threshold default: 0.7. Traces name the check that failed (zscore:temperature_c, sibling:humidity_pct, …) — a refund says which physics convicted the sensor, not just a vibes score.
Fault injection maps failures onto the check that catches them:
POST /sim/fault |
Simulates | Caught by |
|---|---|---|
stuck |
dead sensor / ADC latch | stuck:* |
spike |
loose wire / EMI |
zscore + rate + sibling (+ bounds if absurd) |
drift |
ageing / miscalibration |
sibling:* (slow drift evades z-score alone) |
dropout |
power / radio loss | 503 → hub 502, no money movement |
Honest readings on all four demo devices score ≥ 0.9 in the unit suite. Forged attestation zeroes the score. Unknown device rejected. See test_attestation_and_plausibility.py.
Why this is not "another oracle blog post"
Most "AI + IoT" writeups stop at charts. The interesting engineering is the interface reuse:
- GAIA returns the full Metis-shaped
{status, verified, verify_score, route, trace_id, …}envelope - Engine errors stay HTTP 200 with
status: "error"(never 5xx) so the hub's bounded-retry + fail-open/closed policy applies unchanged - Reputation events from verify pass/fail feed the same trust graph (LUMEN) that already prices agent reputation elsewhere in the stack
- WoT Thing Descriptions sit beside the AIMarket manifest — industrial IoT tooling and agent tooling share one device identity
Math oracles prove compute. Metis judges language. GAIA grounds settlement in the world. Same market. Same escrow. Different ground truth.
Try it
docker pull ghcr.io/alexar76/gaia:latest
docker run --rm -p 9320:9320 ghcr.io/alexar76/gaia:latest
curl -s localhost:9320/.well-known/ai-market.json
curl -s -X POST localhost:9320/ai-market/v2/invoke \
-H 'Content-Type: application/json' \
-d '{"capability_id":"gaia.weather.read@v1","product_id":"gaia.gateway","input":{"device_id":"ws-01"}}'
- Live: iot.modelmarket.dev
- Landing: alexar76.github.io/gaia
-
Deep dive:
docs/iot-physical-oracles.md -
Escrow:
docs/pay-on-verified.md - Related: Metis (cognitive verify) · oracles (17 math doors)
If you're building agents that buy physical facts — weather, air, energy, anything a sensor can claim — don't debit on JSON arrival. Hold the money until physics (or a twin) agrees.
⭐ Map of the whole stack: github.com/alexar76/aicom
Demo fleet is simulated; live device relays and the full AIMarket/Pay-on-Verified wire are real. Treat the public prices as declared demo economics, not a production SLA.

Top comments (0)