DEV Community

Alex
Alex

Posted on

Your agent paid for the weather. The sensor was lying. Who keeps the money?

"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:

  1. Call some weather API or IoT bridge
  2. Parse temperature_c
  3. 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" }
  }'
Enter fullscreen mode Exit fullscreen mode

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": "…" } }
}
Enter fullscreen mode Exit fullscreen mode

Three signatures, three claims:

  1. Device → reading — per-device Ed25519 over device|model|seq|ts|values_sha256
  2. Gateway → response — request-bound X-Provider-Signature (input hash included)
  3. 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
Enter fullscreen mode Exit fullscreen mode

End-to-end:

  1. Buyer invokes gaia.weather.read@v1 with a verify block (intent + wait policy)
  2. Hub calls GAIA → attested reading returned
  3. Hub holds the channel funds (does not debit yet)
  4. Settlement worker POSTs GAIA /v1/verify with the audit string
  5. Pass → capture hold, verify_passed reputation event
  6. Fail → release hold, signed rejection receipt with trace_id: gaia_…, verify_failed
  7. 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"}}'
Enter fullscreen mode Exit fullscreen mode

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)