Particle IoT: list and inspect devices, read variables, call functions, publish events, and manage products and SIMs.
Particle ships in the w6w first-party pack. It declares 13 actions, 2 health checks, and the host runs its code in a sandbox that never sees the credential.
io.w6w.particleParticle manages a fleet of IoT devices — listing and inspecting them, reading variables and calling functions on the hardware itself, publishing events to a whole fleet, and tracking what a cellular fleet is costing in data. Because a call is forwarded to a physical device over its own connection, this app treats “offline” as a fact about the device rather than a failure — a battery-powered sensor that wakes once an hour is offline nearly all the time and working exactly as designed, so listing devices reports counts and last-heard timestamps rather than flagging anything as unhealthy.
Reading a variable or calling a function checks the device’s currently-running firmware first, since the functions and variables it exposes change with every reflash and a missing name looks identical to a missing device. A ping forces a live round trip rather than trusting the cloud’s cached connectivity flag, which goes stale the moment a device loses power without announcing it. Publishing an event defaults to a private stream rather than the public one every Particle account can subscribe to, since a public event can never be recalled.
Devices can also be renamed, made to flash for physical identification, moved into a product fleet, and unclaimed from an account without touching the hardware itself. SIM and diagnostic actions surface signal, battery, memory and data usage — the numbers that explain most field failures before they turn into an outage.
Three routes to the same 13 actions. The Workflow tab is generated from Particle's own manifest and carries its real ids, so it is copy-pasteable; the Code and CLI examples are the same call for any action on any app, so every app-specific value in them is a blank you fill in.
device-get One device, with the VARIABLES and FUNCTIONS its current firmware exposes — the only place that contract is written down, and it changes whenever the device is reflashed.
device-list The account's claimed devices, or a product's fleet. `connected` is NOT a health metric — a sleeping sensor is offline and fine — so this reports the counts and the last-heard spread rather than judging.
device-ping Force a round trip to the device, rather than trusting the cached `connected` flag — which stays true until a lost connection times out. Costs the device a little data, which is real on a metered cellular SIM.
device-rename Change a device's name or notes. Renaming breaks nothing — the id, firmware and connection are untouched — but it is what appears in every alert somebody has to triage.
device-signal Make one device flash a rainbow so a person can find it physically — the only way to correlate a device id with a box on a wall. Runs no firmware and changes no state.
device-unclaim Remove a device from this account. The DEVICE IS UNTOUCHED — same firmware, still connecting, still using cellular data — it just no longer belongs here. Not a way to decommission hardware.
diagnostics-get The device's last reported vitals — signal strength, battery and free memory, which explain most field failures and none of which appear in `device-get`. These are the LAST reported values, so an offline device still has them, from just before it went quiet.
event-publish Publish an event that subscribed devices receive — one call reaches a whole fleet. PUBLIC events are visible to every Particle account in the world and cannot be recalled, so this defaults to private, unlike the API.
function-call Call a function on the device's firmware — which in the field actuates real hardware, and the cloud cannot tell a relay from a blink. Returns a single INTEGER, because that is the entire return channel a Particle function has.
product-device-add Move devices into a product fleet. The product then OWNS them — they leave the claiming account, and an active product firmware release will reflash them on their next connection, without anyone touching the device.
product-list The products this token can reach. A product OWNS its devices — they are a different list from an account's claimed devices, and an automation pointed at the wrong one sees nothing and reports no error.
sim-list Cellular SIMs and their data usage — the only visibility into a fleet's running cost before the invoice. A SIM over its data limit silences its device while looking like an outage.
variable-get Read a value off the device itself — a round trip to hardware, so the number is true NOW and an unreachable device times out rather than returning something stale.
A workflow step names the app and the action, and the editor fills in the
connection when you pick one. This is the Step shape from the
workflow spec, carrying Particle's real ids.
{
"manifestVersion": "2",
"name": "particle-example",
"steps": [
{
"id": "device-get",
"uses": {
"app": "io.w6w.particle",
"action": "device-get",
"connection": "conn_YOUR_CONNECTION_ID"
},
"with": {
"deviceId": "<deviceId>"
}
}
]
}device-get device-list device-ping device-rename device-signal +8 more actions available
Every app-specific value here is a blank you have to fill in. An
app action is reached through the connection that authenticates it, so the
address is a connection id, not the app id — and connections belong to your account,
so a public page cannot know yours. Create one for Particle, then fill in
the three blanks: conn_YOUR_CONNECTION_ID, the action key, and the
parameters that action declares. The call itself is real — the shape is transcribed
from the studio's own snippet builder, which prints the same kind of blanks — but
nothing in it is specific to Particle. The Workflow tab is where this app's
real ids are.
npm install @w6w/sdkyarn add @w6w/sdkpnpm add @w6w/sdkdeno add npm:@w6w/sdkimport { W6wClient, isActionRun } from "@w6w/sdk";
// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.
const client = new W6wClient();
const envelope = await client.run({
urn: "conn_YOUR_CONNECTION_ID",
action: "device-get",
payload: {
deviceId: "<value>",
},
});
if (isActionRun(envelope)) console.log(envelope.value); npm install -g @w6w/cli w6w run conn_YOUR_CONNECTION_ID --action device-get --payload '{"deviceId":"<value>"}' Give an AI agent Particle — without giving it Particle's credentials. One MCP endpoint exposes every app, function and workflow the caller is entitled to, as tools it can discover and run. Access is granted per team while we onboard.
One tool call{
"name": "w6w_invoke",
"arguments": {
"ref": "app:io.w6w.particle#device-get",
"input": {
"deviceId": "<deviceId>"
}
}
}
Every tool names its target with a single ref. The
app: form above doesn't name a connection at all — the
host resolves which of the caller's Particle connections to sign
with, and refuses rather than guesses when the answer is ambiguous.
The token is attached host-side, at the moment of the call. It is never a tool argument, never in the model's context, and never in a transcript — so a prompt injection has nothing to exfiltrate.
Tools are derived per end user from what that person has actually connected and is entitled to — not one shared bot identity carrying the union of everyone's access.
Multi-step work runs on the workflow engine and returns a run handle the agent can poll — retries, branching and state survive the conversation that started them.
Particle's declared health checks are on the surface too, so an agent can tell "the vendor is down" from "your credential expired" before it burns a retry on either.
The MCP surface is part of the hosted platform. Particle itself is MIT, and the runtime that executes it is source-available (FSL).
Particle declares its own checks, so its health is a property of the app rather than something the host guesses at.
Reads status.particle.io, separating the REST API from DEVICE CONNECTIVITY. They fail independently: a connectivity outage leaves the API answering normally while every affected device is unreachable, and nothing about the API looks wrong.
Not checkable. Particle publishes no rate-limit header and its limits are PER ENDPOINT, so there is no single number. The budget that actually runs out on a cellular fleet is DATA — `sim-list` reports that, and flags SIMs cut off for exceeding it.