defineDevice declares a device the agent can control: each command becomes a tool the model can call, and each trigger is a handler that runs when the device reports an event. defineDeviceTrigger declares a standalone device trigger that is pushed and versioned on its own and that any device on the agent can fire. Register the results on LuaAgent under devices and deviceTriggers. The device-side client is documented under Devices.
Verified against lua-cli 3.33.0.
Quick example
A printer with two commands and one built-in trigger:src/devices/LabelPrinter.ts
Functions
defineDevice()
Returns aLuaDevice; identical to new LuaDevice(config).
string
required
Device identifier. Must equal the name the device connects with.
lua compile warns unless it matches ^[a-z][a-z0-9-]*$. Hyphens become underscores in the tool names the model sees.string
default:"''"
Shown in
lua devices list.string
Group name, for example
printers. Enables the fan-out tools described under Tools the model receives and the lua devices list --group <name> filter.Record<string, DeviceCommandConfig>
default:"{}"
Commands the agent can send, keyed by command name.
Record<string, DeviceTriggerConfig>
default:"{}"
Events this device can fire, keyed by the exact trigger name the device sends.
DeviceCommandConfig
string
required
What the command does. This is the tool description the model reads.
ZodType
Input schema; becomes the tool’s input schema. Omit for a command without arguments.
number
default:30000
How long the platform waits for the device’s reply.
{ maxAttempts: number; backoffMs: number }
Retries after a timeout, a server error, or a network error, waiting
backoffMs × attempt between attempts. An offline device or a rate limit is not retried. Default: one attempt.DeviceTriggerConfig
string
required
When the trigger fires. Shown in listings.
ZodType
Schema for the payload the device sends.
(payload, context) => Promise<any>
Handler that runs on the platform when the device fires the trigger.
context is { device: { name }, trigger: { name, triggerId } }; the agent member in the type is not populated at runtime, so hand the event to the agent with Agents.invoke or return { startWorkflow }. The handler receives no environment variables, so env() is empty for every key; keep identifiers such as the agent ID in a constant. A trigger without execute is recorded but does nothing.defineDeviceTrigger()
Returns aLuaDeviceTrigger; identical to new LuaDeviceTrigger(config). A standalone trigger is compiled and pushed as its own primitive (lua push device-trigger) and matches an event from any device on the agent. 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.
string
required
Trigger identifier. Must be exactly the string the device sends as the trigger name; no case or separator mapping is applied.
lua compile warns unless it matches ^[a-z][a-z0-9_-]*$.string
default:"''"
When the trigger fires. Shown in listings.
ZodType
Schema for the payload the device sends.
(payload, context) => Promise<any>
required
Handler as for a built-in trigger;
context.device.name names the device that fired it. The type declares context as { agent, device: { name } }, but the runtime passes { device: { name }, trigger: { name, triggerId } } and never populates agent. lua compile fails with Device trigger must have an execute function when it is missing.src/devices/JamDetected.ts
Tools the model receives
Every command of a device declared withdefineDevice is offered to the model as a tool while the device is registered, online or not; a call to an offline device returns DEVICE_OFFLINE. A self-describing device’s commands are offered only while it is online. You do not write a LuaTool per command.
Hyphens in the device and group names are replaced by underscores. The tool description is
[Device: <device>] <description>. If the device is offline, this will return an error. An agent exposes at most 128 device tools; further commands are dropped with a warning in the logs. Fan-out tools exist only for devices declared with defineDevice. A fan-out call addresses every registered device whose connection reported the group, online or not; an offline member fails and is counted in failed. Failed calls return error values DEVICE_OFFLINE, TOO_MANY_REQUESTS, TIMEOUT, DEVICE_ERROR, or MAX_RETRIES.
Trigger dispatch
- The platform matches the trigger name the device sends by exact string equality: first against the
triggersof the device that sent it, then against standalone device triggers on the agent. An unmatched name is logged and dropped. executereceives the payload and{ device: { name }, trigger: { name, triggerId } }and has up to 10 minutes to return, the platform’s default cap for event handlers.- Events are delivered at least once from a durable queue: a handler that throws or times out is run again, up to 3 attempts 60 seconds apart, with the same
triggerId. Make handlers idempotent. - A return value of
{ startWorkflow: { name, input?, idempotencyKey?, correlationKey?, tags?, initialState?, notify?, replyTo?, onBehalfOf? } }starts a run of the named workflow on the agent; the same contract as aLuaTriggertransform. Any other return value is logged. - A thrown error is logged and the attempt is retried as above; nothing is sent to the end user.
Classes
LuaDevice and LuaDeviceTrigger are exported for new LuaDevice(config) and new LuaDeviceTrigger(config); they have no methods.
class
class
CLI commands
lua deploy has no device types, and devices and device triggers aren’t part of an agent version. --auto-deploy publishes the pushed version in the same command; without it the push asks whether to publish, and --force answers no. 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.
Types
All of these are exported from'lua-cli'.
interface
{ name; description?; group?; commands?; triggers? } as documented under defineDevice().interface
{ description; inputSchema?; retry?; timeoutMs? }.interface
{ description; payloadSchema?; execute? }.interface
{ name; description?; payloadSchema?; execute }.See also
- Devices — transports, commands as tools, offline behavior
- Commands and tools — how a device describes its commands
- Device triggers — firing a trigger from the device side
lua devices— the device management commandAgents— invoking the agent from a trigger handler

