Zum Hauptinhalt springen

Worked example: thermal router

Goal: a state machine that polls a weather API every 10 Zeqonds, converts the returned temperature from Fahrenheit to a custom degree-day metric, and emits a routing event when the metric crosses a threshold. End-to-end this uses:

  • One custom operatorDEGDAY — that the catalogue doesn't ship.
  • One custom protocol — the weather external API.
  • One state contract — the rule that ties them together.

Step 1 — derive the operator

curl -X POST https://zeqapi.com/api/zeq/agent/operators/derive \
-H "Authorization: Bearer zeq_ak_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"computation_needed": "Heating degree-day from current temperature: max(0, base − T_current) where base = 65°F",
"domain": "thermodynamics",
"parent_operators": ["NM23"],
"hulyas_coupling": true,
"generation": 1
}'

Response (excerpt):

{
"operator_id": "DEGDAY",
"formula": "HDD = max(0, T_base − T_current) · (1 + α sin(2π·1.287·t))",
"verification": { "passed": true, "precision": 0.00012, "test_cases": [/* 3 cases */] },
"registered": true
}

Verification passed at 0.012% — well under the 0.1% bound. The operator is now callable on your machine. ZEQ cost: 50.

Step 2 — register the weather API

Open the workbench Queries tab → APIs sub-tab → New API. Or:

curl -X POST https://zeqapi.com/api/zeq/external-apis \
-H "Authorization: Bearer zeq_ak_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"name": "weather",
"base_url": "https://api.openweathermap.org/data/2.5",
"auth_header": "Authorization",
"auth_value": "Bearer <YOUR_OPENWEATHER_KEY>",
"rate_limit_per_minute": 60
}'

The auth value is encrypted at rest. The framework will manage retries, rate-limiting, and entangled-state logging for every call your contracts make through this API.

Step 3 — write the contract

The cleanest way is the workbench's Queries tab in Guided mode — answer 7 questions, hit Deploy. But here's the underlying JSON the wizard produces, in case you'd rather write it directly:

{
"name": "heating_degree_day_router",
"version": "1.0",
"states": {
"polling": { "initial": true },
"routed": {}
},
"transitions": [
{
"from": "polling", "to": "polling",
"operator": "DEGDAY",
"proof_required": true,
"auto": false,
"trigger": { "kind": "recurring", "every_zeqonds": 10 },
"pre_actions": [
{
"type": "api_call",
"api": "weather",
"path": "/weather",
"method": "GET",
"params": { "q": "London", "units": "imperial" },
"into": "wx"
}
],
"post_actions": [
{ "type": "emit", "event": "hdd_computed" }
]
},
{
"from": "polling", "to": "routed",
"operator": "KO42",
"proof_required": false,
"auto": false,
"trigger": {
"kind": "on_event",
"event": "hdd_computed",
"where": "payload.hdd > 5"
},
"post_actions": [
{ "type": "emit", "event": "route_to_heat" }
]
}
],
"observers": [],
"audit_clock": true,
"zeqond_tick_rate": 1
}

Two transitions:

  1. The poller. Every 10 Zeqonds (~7.8 seconds), fetch London weather, run DEGDAY over the response, and emit hdd_computed carrying the degree-day. (from and to are both polling — a self-loop, so the poller keeps re-arming.)
  2. The router. Whenever an hdd_computed event lands AND the current HDD exceeds 5, emit route_to_heat. Downstream contracts (yours or someone else's, in any state machine subscribed to your tag) can react.

Deploy — POST the definition to your machine's create route (authenticated with your session or your machine key zsm_…; a compute key zeq_ak_… is for compute, not contract management):

curl -X POST https://zeqapi.com/api/chain/<your-slug>/contracts \
-H "Authorization: Bearer ${ZSM_KEY}" \
-H "Content-Type: application/json" \
-d @heating_degree_day_router.json

Or paste the JSON into the Contract IDE (/apps/contract-ide/) and click Deploy — same validation, same result. From the terminal: contract deploy <json>.

Step 4 — watch it tick

Open /state/?slug=<your-slug> in another tab. Within ~10 Zeqonds you'll see:

  1. A pre_action.api_call.weather row — the upstream call, with redacted auth, status code, and duration.
  2. A compute row — operator DEGDAY, inputs = the weather response, output = the computed HDD, precision achieved.
  3. A post_action.emit row — event = hdd_computed, payload = { hdd: <value>, T_current: <temp>, T_base: 65 }.

When HDD crosses 5, the second transition fires and you'll see a fourth row: post_action.emit with event = route_to_heat.

Every row is signed and verifiable on /transparency/. You can replay the contract from any past zeqond:

GET /api/contracts/<contract-id>/replay?replay_from_zeqond=<zeqond>

Step 5 — promote DEGDAY (optional)

After three successful tick cycles at ≤0.1% precision, promote DEGDAY into the public catalogue so other machines can use it:

curl -X POST https://zeqapi.com/api/zeq/agent/operators/promote \
-H "Authorization: Bearer zeq_ak_<your-key>" \
-d '{ "operator_id": "DEGDAY" }'

If the fitness criterion isn't met yet the response tells you exactly which case failed and what precision was achieved. Re-derive with adjusted parents if needed.

Cost summary

For a one-day run at 10-Zeqond cadence (~11,100 ticks):

ActionCost
Derive DEGDAY (once)50 ZEQ
11,100 compute ticks (5 ZEQ each)55,500 ZEQ
11,100 api_call retries (1 ZEQ each)11,100 ZEQ
Promote (once)0 ZEQ

The Free tier mints 100 ZEQ/day. Starter mints 1,287 ZEQ/day. Production cadence + paid tier comfortably covers this; experimentation at lower cadence costs single-digit ZEQ per hour.

Recap

The same primitives the framework's built-in machines use are available to you:

  • Math you teach the kernel becomes part of the catalogue once verified.
  • External data you wire in is a first-class protocol with encryption, retries, rate-limits, and entangled-state logging.
  • The contract that glues them is one JSON document, deployable from the IDE or one curl command.

Nothing about this example is special-cased. The same pattern works for genome decoding, market-making, robotics control loops, climate modelling, chemistry simulation — anywhere you need math that isn't in the catalogue and data that isn't on your local machine.

Where next