Skip to main content

Industrial and IoT: when the action is physical

Track: Industrial and IoT · In the room: ASSA ABLOY, Nibe · Seed use case: access-anomaly triage, or heat-pump fleet optimisation on a schedule.

Who this is for

  • ASSA ABLOY — no Cloudflare developer-platform footprint at all today. Millions of installed access-control endpoints, and a product where the failure modes are a door that opens for the wrong person or refuses to open for the right one.
  • Nibe — barely any footprint today. A fleet of connected heat pumps in Nordic homes, where "optimisation" means somebody's house temperature and somebody's electricity bill.

You are the two accounts furthest from this platform, which is exactly why this track is worth an hour. Both of you already have the hard part: a large fleet of connected devices reporting state. What neither of you has is something that watches that fleet continuously, forms an opinion, and is trusted enough to act on it.

And you share the constraint that makes this track the most interesting one in the room: in your industries, the agent's action is physical. Everyone else is arguing about a refund or a ticket. You are arguing about a lock and a radiator. That raises the bar on the approval gate and it also makes the demo unforgettable.

Synthetic data only

Invented sites, invented device ids, invented occupants. Access logs and in-home telemetry are both personal data. Nothing real goes into a shared account today.

Three agent use cases

1. Fleet-anomaly triage — the seed use case

Same architecture, two skins. Pick whichever fleet you know.

Doors: an access-control anomaly — a credential used at two sites forty kilometres apart within ten minutes, a door held open for eleven minutes at 03:00, a badge that has started working hours it never worked before.

Heat pumps: a unit whose compressor is running far longer than its neighbours to hold the same indoor temperature, a defrost cycle firing twice as often as its cohort, a house losing heat faster than its own history says it should.

  • Trigger. A scheduled sweep over the fleet. Nothing is pushed; the agent goes looking.
  • What the agent decides. Whether this reading is genuinely abnormal for this site (a warehouse door legitimately stays open at shift change; a house with the windows open in April is not a broken heat pump), how urgent it is, and what intervention fits.
  • What it does — the tools. assess_device produces a verdict with the baseline it compared against, and propose_intervention drafts the specific change or action.
  • Human in the loop? Yes, on anything physical, without exception. Flagging, ranking and notifying are free. Revoking a credential can strand a night-shift worker outside a building in February. Changing a heat curve changes the temperature in someone's home. The agent should be allowed to be confident and still not allowed to act.

2. Installation-quality reviewer

  • Trigger. A device comes online for the first time, or reports its commissioning values.
  • What the agent decides. Whether the installation looks correct — sensor readings in plausible ranges, configuration consistent with the building or property type, no obviously swapped sensors, no default values left in place.
  • What it does — the tool. review_commissioning produces a pass, a warning with the specific suspect values, or a fail, and drafts a note to the installer.
  • Human in the loop? Yes, as the installer's decision. The agent cannot see the site. It can say "these two sensor readings look transposed", which is enormously useful, and it cannot say whether that is true. Catching a bad install in week one instead of at the first winter callout is most of the value of this whole track.

3. Service-window planner

  • Trigger. A weekly sweep of devices flagged as degrading but not failed.
  • What the agent decides. Which devices should be visited together — geography, the same likely part, the same technician skill — turning a list of individual faults into a route.
  • What it does — the tool. plan_route groups the flagged devices into a proposed visit schedule with reasoning per group.
  • Human in the loop? Yes, as a plan a dispatcher edits. Nobody dispatches a van on an agent's word, but everyone would rather edit a plan than build one.

The 60-minute cut

Build use case 1. Cut it to: a scheduled sweep, a per-site baseline, and an intervention that will not fire without a human.

In scope:

  1. Eight synthetic devices in an array. Give each one a site id, a device type, and a short history of readings. Make one clearly anomalous, one anomalous-looking but explainable by its own history, and six normal.
  2. A scheduled sweep with the Agents SDK this.schedule(), every 60 seconds so it fires during your demo. Say out loud that production would be every 15 minutes, or hourly.
  3. A rolling per-site baseline held in the agent's own storage — the sweep compares each reading against what that site normally does, not against a global constant. This is the difference between an agent and an alert threshold.
  4. A Workflow that pauses on the intervention and only proceeds on an explicit human event.
  5. A route that would perform the physical action and refuses without approval, loudly.

Out of scope, and say so: device connectivity, MQTT, real protocols, authentication, timezones, and machine learning. A mean and a standard deviation over the last few readings is a perfectly respectable baseline for sixty minutes, and it is honest about being one.

The demo that wins. Let the sweep find the anomaly on its own while you are still talking. Then try to apply the intervention and let your own system refuse you. Approve it, watch it go through, and then show the record: what the agent recommended, who approved it, and when. For an access-control or heating audience that record is the product — and you built it in an hour, having never deployed on this platform before.

Primitives — exactly three

  1. Schedules (this.schedule() on the Agents SDK Agent class). Fleet problems are found by sweeping, not by being notified — a heat pump working too hard never raises an error, and a door held open only matters after it has been open too long. Scheduling from inside the agent keeps the sweep next to the baseline it needs, so detection and memory never drift apart. A cron-triggered Worker plus a database is the same thing with two more moving parts.
  2. Persistent Durable Object state. An anomaly is defined relative to normal, and normal is per site. The agent's embedded SQLite (this.sql) is where the rolling baseline lives, updated on every sweep, strongly consistent, and it hibernates between sweeps so an idle fleet costs nothing. Recomputing a baseline from a shared table on every pass is both slower and, once two sweeps overlap, wrong.
  3. Workflows. A physical intervention is a multi-step action that has to be exactly-once and has to survive waiting for a person. step.waitForEvent() holds the run open for hours without consuming resources, and step.do() checkpointing means a retry cannot revoke the same credential twice or apply the same setpoint change twice. This is also, not incidentally, your audit trail.

Skip Browser Rendering (nothing to render) and skip AI Search — you are reasoning over numeric device state, not documents. AI Search becomes the right third primitive the moment you want the agent to cite an installation manual, which is use case 2.

Paste-ready starter prompt

Scaffold the starter first:

npm create cloudflare@latest -- team-industrial-fleet-triage --template cloudflare/agents-starter
cd team-industrial-fleet-triage

Then paste this into your coding agent:

I'm working in a fresh clone of Cloudflare's agents-starter template. The agent code is in
src/server.ts and the React client is in src/client.tsx. I have 60 minutes. Keep the
existing chat agent working — extend it, don't replace it.

Build a fleet-anomaly triage agent for connected industrial devices, where every physical
action requires human approval.

1. Add a hardcoded array of 8 synthetic devices to src/server.ts. Each has: deviceId, siteId,
deviceType, and a readings array of 10 entries with a timestamp and a numeric value. Use
heat-pump compressor runtime minutes per hour as the metric. Make device 3 clearly
anomalous against its own site history, make device 6 look high in absolute terms but
normal for its own site, and leave the rest normal. Invented data only.

2. On every sweep, maintain a rolling baseline per siteId in the Agent's SQLite storage using
this.sql: the mean and standard deviation of that site's recent readings. Anomaly detection
must compare a reading against ITS OWN SITE's baseline, never against a global constant.

3. Use this.schedule() to run the sweep every 60 seconds. For each device whose latest reading
is more than 2 standard deviations from its site baseline, call a tool called assess_device.

4. assess_device uses a Workers AI model and returns JSON: isAnomaly (boolean), severity (low,
medium, high), explanation (two sentences that state the site baseline and this reading),
intervention (one of none, notify_owner, adjust_setpoint, dispatch_technician), and
requiresApproval (boolean — true for anything that changes device behaviour). Store the
verdict keyed by deviceId, updating rather than duplicating on re-assessment.

5. Add a Cloudflare Workflow called Intervention in a new file, with steps as step.do():
a) prepare — record the proposed intervention and the reasoning
b) await_approval — step.waitForEvent() with a generous timeout, waiting for an event of
type "intervention-decision". This step must NOT be skippable for any intervention
where requiresApproval is true.
c) apply — record the applied change, who approved it, and when
d) notify — log a message to the site owner (do not actually send anything)
Import WorkflowEntrypoint, WorkflowStep and WorkflowEvent from "cloudflare:workers", and
add the workflow binding to wrangler.jsonc.

6. Add a POST /apply/:deviceId route that represents physically changing the device setpoint.
It must REFUSE with HTTP 403 and a clear JSON explanation unless the intervention for that
device has an approved decision recorded. Log every attempt, approved or refused. Put a
comment above it explaining this is a deliberate human approval gate because the action
changes the temperature in someone's home.

7. Add routes:
GET /fleet HTML page: every device, its site baseline, latest reading,
verdict, proposed intervention, and approval state. Show
PENDING APPROVAL prominently.
POST /decide/:deviceId sends the "intervention-decision" event with approved
true or false, and an approver name from the body

Requirements: TypeScript. Route every Workers AI call through AI Gateway by passing
{ gateway: { id: "agenthack" } } as the options argument. Run `npx wrangler types` after
changing wrangler.jsonc. Then deploy with `npx wrangler deploy` and give me curl commands
that prove /apply refuses before approval and succeeds after it.

The Worker name team-industrial-fleet-triage follows the shared-account rule <team_prefix>-<slug>. Eight teams deploy into one account today, so if the Scoping agent issued you a different prefix, use that one instead.

What "production" looks like

  1. Give the agent an addressable identity per site, not per fleet. One agent instance per site or per installation, hibernating between sweeps, means the baseline lives next to the device it describes and scales to a million units without a single shared hot table. It also makes deletion trivial, which matters when the reading is somebody's home and they ask you to remove it.
  2. Make the approval gate carry an authenticated identity and a reason code. Put your IdP in front of the decision endpoint so every physical change is attributable to a named person who was shown the agent's reasoning. Then track how often humans override the agent, split by intervention type — that ratio tells you precisely which actions are ready to be automated further and which are not, and it is a much better guide than intuition.
  3. Widen the baseline from statistical to contextual. Weather, occupancy, tariff prices, shift patterns. Every context signal you add removes a class of false positive, and false positives are the only thing that will kill this system inside your organisation — an agent that cries wolf about a warehouse door at shift change gets switched off in a fortnight, regardless of how good the architecture is.

Next: the Level Up page explains each primitive, and the cheat sheet has the snippets. Both are in the sidebar.