bench-sensor with one command, and shows how to go live and test. Any board works the same way: for a microcontroller, follow the Raspberry Pi Pico W guide after step 2. The device opens one outbound connection over port 443, so it needs no inbound port or public address.
1. Get set up
You need Node 18 or later. If you build with Claude Code, add the Lua plugin first; inside a Claude Code session run:Claude Code
/lua-doctor checks Node, lua-cli, and your sign-in and offers to fix what’s missing. See Claude Code plugin.
Then install the CLI, sign in, and create the agent project. Choose Email when lua auth configure asks for a method: issuing a device credential needs an email sign-in.
2. Issue the device credential
A device connects with its own credential, bound to one agent and one device name. The API keys on the dashboard don’t work on a device; the gateway refuses them. From the agent project, issue one and write it to a file in the folder the device will run from:LUA_AGENT_ID, LUA_DEVICE_NAME, and LUA_DEVICE_CREDENTIAL, with mode 600. The credential grants commands and triggers by default; add --operations commands,triggers,assets.upload if the device will upload files. Keep the file out of version control. See Create a device credential for rotation and revocation.
3. The primitives that matter
4. Your first command
In the device folder, install the Node device client and a TypeScript runner:device.ts
bench-sensor connected. The command list is sent when the device connects, so nothing needs to be pushed: from the agent project, ask the agent.
5. Go live and test
Skills and the other code primitives go live through an agent version:lua deploy persona --set-version latest --force serves it, and a promote doesn’t change it. See Release an agent to production.
Devices and device triggers are not part of an agent version. A self-describing device like the one above needs no push. Push a defineDevice declaration, with its trigger handlers, on its own; it reaches the agent on the next turn. Push a standalone defineDeviceTrigger with --auto-deploy, because it runs only once its version is published:
test-trigger line assumes you have written a temperature_alert handler as in Handle device triggers.
status prints 🟢 Device 'bench-sensor' is online. test sends the command and prints the device’s reply, or the device’s own error. test-trigger fires the trigger through the live pipeline, so the handler really runs, and lua logs --type device-trigger shows its run.
Things that save you time
- Write the credential to a file.
--outplusset -a; . ./.env.device; set +asaves copying secrets around. Use one credential per device; the agent ID and device name must match it exactly. - Don’t use a dashboard API key on a device. It fails with
AUTH_FAILEDover Socket.IO andNot authorizedover MQTT. Issue a device credential. - Sign in by email.
lua devices credentialrefuses an API-key sign-in, and aLUA_API_KEYin your shell or the project’s.envoverrides the email session. has never connected to this agentfromlua devices statusmeans the device connected with a different name or agent, or not at all.lua devices listshows every device, including self-describing ones, withonline,offline, ordisabled.- Use underscores in command and trigger names. Hyphens in a device name become underscores in tool names:
bench-sensor→device__bench_sensor__read_temperature. - Write descriptions for the model. A command’s description and the persona decide when the agent calls it.
- Test without chatting.
lua devices test --command … --cichecks a command andlua devices test-trigger --trigger …runs a handler; both run in scripts. - Make trigger handlers idempotent. They are delivered at least once and run up to three times.
- Reconnect daily. A self-describing device loses its command tools 24 hours after it connected, until it reconnects.
- Scaffold with Claude Code.
/lua-new deviceand/lua-new device-triggercreate, register, and compile the declarations.
Go deeper
How devices work
The connection lifecycle: handshake, tools, triggers, heartbeats, reconnection.
Create a device credential
Operations, the REST route, rotation, and revocation.
Expose device commands as tools
Input schemas, timeouts, retries, and the results the model sees.
Handle device triggers
Fire an event and run a handler on the platform.
Run a device on a Raspberry Pi Pico W
A microcontroller as a device, with the single-file MicroPython client.
Reliability and limits
Reconnection, heartbeats, offline semantics, and every cap.

