- A connected device with a credential that grants
triggers, whichlua devices credentialgrants by default. - The agent project signed in, and the agent ID from
agent.agentIdinlua.skill.yamlif the handler hands the event to the model. A device trigger handler runs with an emptyenv(), 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.
- Node
- Python
- MicroPython
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.- Inline on defineDevice
- Standalone defineDeviceTrigger
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 The platform runs the latest live handler for a name.
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.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 firesdevice_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
The log says the trigger was skipped
The log says the trigger was skipped
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.trigger_error with RATE_LIMITED
trigger_error with RATE_LIMITED
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.trigger_error with OPERATION_FORBIDDEN
trigger_error with OPERATION_FORBIDDEN
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.

