Skip to main content
After this guide, an event your device sends runs code on the platform: stored, handed to the model, or turned into a workflow run. Use a device trigger when the hardware decides when something happens; when the model should ask the device, expose a command instead. Verified against lua-cli 3.45.0. Before you begin
  • A connected device with a credential that grants triggers, which lua devices credential grants by default.
  • The agent project signed in, and the agent ID from agent.agentId in lua.skill.yaml if the handler hands the event to the model. A device trigger handler runs with an empty env(), so keep the ID in the handler file rather than in an environment variable.
1

Fire the trigger from the device

Send a name and a JSON payload. Use underscores in the name; the platform matches it character for character against your handler.
device.ts
trigger() resolves when the platform has queued the event and rejects with Trigger 'temperature_alert' ACK timeout (10s) if no acknowledgment arrives.
2

Write the handler

A handler runs on the platform with the payload and { device: { name }, trigger: { name, triggerId } }, and has up to 10 minutes to return, the platform’s default cap for event handlers. Declare it inline on the device or as a standalone trigger that any device on the agent can fire.
src/devices/BenchSensor.ts
3

Register the declarations on the agent

Only declarations referenced from LuaAgent are compiled.
src/index.ts
4

Publish the handlers

Devices and device triggers are not part of an agent version. A pushed defineDevice declaration reaches the runtime on the agent’s next turn whether or not you publish it; --auto-deploy only records it as the active version. A standalone defineDeviceTrigger runs only after its pushed version is published, with --auto-deploy or the push prompt. --force alone skips the prompt and leaves the version unpublished.
The platform runs the latest live handler for a name.
5

Verify

Fire the trigger from the device, or from the agent project without the device, then read the handler’s run.
lua devices test-trigger sends the event through the same live pipeline as the device, with the same 1 MB payload cap and rate limit, so the handler really runs; the device receives nothing and doesn’t need to be connected, but a disabled device is refused.A trigger with no live handler is logged as skipped and dropped; the device still receives received: true, because the acknowledgment means queued, not handled.

Options you may need

Start a workflow instead of a chat turn

Return { startWorkflow: { name, input, idempotencyKey } } from execute to start a run of a workflow on the agent; the fields match a LuaTrigger transform. Any other return value is logged.

React to connections

The platform fires device_connected with { deviceName, connectedAt, metadata } when a device’s connection opens and device_disconnected with { deviceName, disconnectedAt } when it closes or its MQTT will is published; a device timed out by the heartbeat sweep fires neither. Handle them with a defineDeviceTrigger of the same name.

Delivery guarantees

Events are delivered at least once from a durable queue: a handler that throws or exceeds its time limit is run again, up to 3 attempts 60 seconds apart, so make handlers idempotent; trigger.triggerId is the same on every attempt. The platform never sends a trigger_result back to the device, so the clients’ trigger-result handlers don’t run.

If it isn’t working

No live handler matched the name. Check the exact spelling on both sides (temperature_alert and temperature-alert are different names), and that the push finished with the version live.
The agent received more than 10 triggers in one second across all its devices. Batch readings into one payload or fire less often. Only the Node Socket.IO client surfaces the event; the MQTT clients don’t subscribe to trigger_error, so their trigger() call times out after 10 seconds instead.
The credential doesn’t grant triggers. Issue a new credential with the operation; over MQTT the publish is denied silently instead.

Next steps

defineDevice and defineDeviceTrigger

Every handler field, the dispatch rules, and startWorkflow.

Triggers

How HTTP triggers differ from device triggers.

Factory monitor

A MicroPython device that fires anomaly triggers.