- A project created with
lua initand signed in withlua auth configure(Install and sign in). - The sender’s payload shape and how it authenticates (a shared header or a body signature).
1
Create the trigger and copy its URL
lua triggers create registers the trigger and prints ✅ Trigger "order-created" created, the URL under 🔗 Trigger URL (paste it anywhere):, and a curl line that fires it. The token in the URL is the only credential; treat the URL like an API key.Type: URL in lua triggers list): every POST body becomes a message to the agent, prefixed with [Trigger: order-created] and any --instruction. The turn runs as you, the creator, with your tools and data, unless transform returns another userId; no end user receives anything unless the model calls a tool that sends a message.2
Shape events in code
defineTrigger has no execute. Up to four slots run on the platform per delivery, in order: verify (401 when false), filter (200 and dropped when false), transform (the event becomes the message), and tool (one tool, no model turn). The slots share a 15-second budget and can read env().src/triggers/order-created.trigger.ts
ctx.body in every slot. A sender that signs its payload is verified over ctx.rawBody, the exact bytes received. Store the token with lua env production -k SHOP_WEBHOOK_TOKEN -v <token>.3
Register it and compile
Add the trigger to
LuaAgent.triggers; unreferenced triggers aren’t compiled. The file below is the quickstart’s; if yours differs, add only the highlighted lines to your own LuaAgent.src/index.ts
lua compile checks the slots.Output
lua compile fails when no slot is set and warns when both tool and transform are declared: the tool wins.4
Push and release the version
lua push trigger uploads the compiled slots as a version of the trigger with that name and links the lua.skill.yaml row to the trigger from Step 1 by name: one trigger, one URL (the server refuses a duplicate name). Without Step 1, the push creates the trigger and lua triggers list prints its URL. lua deploy trigger then creates and promotes an agent version scoped to this trigger, so the slots are live at once and lua triggers list shows Type: SDK.lua push all --ci --force, then lua version create --ci -m "Add order-created trigger", which prints ✓ Created v<n> (staged). Run `lua version promote v<n>` to deploy., then lua version promote <n> (<n> or v<n>, no confirmation; in a script n=$(lua version list --limit 1 --json --ci | jq -r '.[0].version')) (Release an agent to production).5
Paste the URL and fire it
There is no The response is
lua test trigger, so this request is the first test. Give the sender the URL, or send one event yourself with the header verify expects.200 with { "status": "accepted", "executionId": "…" } once the slots pass; the turn runs afterwards. A wrong x-shop-token answers 401; a type other than order.created answers 200 and is dropped.6
Verify
Every delivery is a row in the trigger’s log for 90 days, newest first, with status, duration, payload, reply, and tools used.Your event shows as
COMPLETED with the reply text once the turn finishes, or ACCEPTED (in flight) while it runs; a bad token shows as REJECTED (verify failed → 401) and a filtered event as SKIPPED (filtered out). --json returns the rows as data.Options you may need
Run one tool instead of a model turn
Replacetransform with tool: { name: 'lookup_order', input: (ctx) => ({ orderId: ctx.body.data.orderNumber }) }: name is a string literal naming a tool in one of the agent’s skills, and input maps the event to its arguments. No message is sent; the result goes on the log row. To start a workflow run instead, return { startWorkflow } from transform (LuaTrigger reference).
Use tool (or a webhook) for anything that must happen on every delivery, such as sending a message, writing a record, or handing off. With transform or an --instruction, the model decides whether to call the tool and can reply without calling it (Actions that must happen).
Rotate a leaked token
lua triggers rotate-token --trigger order-created prints a replacement URL and the old one stops working at once; lua triggers deactivate --trigger order-created pauses deliveries without changing the URL.
If it isn’t working
Every delivery is REJECTED (verify failed → 401)
Every delivery is REJECTED (verify failed → 401)
The header the slot compares isn’t what the sender sends (keys are lowercase in
ctx.headers), or SHOP_WEBHOOK_TOKEN isn’t set in production. Set it with lua env production -k SHOP_WEBHOOK_TOKEN -v <token>; slots read it on the next delivery.A delivery is FAILED
A delivery is FAILED
transform returned nothing, a slot threw or ran over its budget (the sender got 500), or the turn or tool failed after the 200. Lua never redelivers, so the sender must send again; use filter, not an empty transform, to skip an event.A delivery is COMPLETED but the tool never ran
A delivery is COMPLETED but the tool never ran
COMPLETED means the agent replied, not that a tool ran. Check the tools used on the log row: when it is empty, the model answered without calling the tool, and its reply may still say the work was done. Move the action to tool (see Run one tool instead of a model turn) or to a webhook so it runs on every delivery.lua push says a trigger has no code in this project (or was not found in compiled output)
lua push says a trigger has no code in this project (or was not found in compiled output)
The trigger exists on the server but not in your
LuaAgent (for example, one created in the dashboard or with lua triggers create). lua push skips it and changes nothing on the server, and lua version create and lua version promote don’t delete it. Define it with defineTrigger and add it to LuaAgent.triggers only if you want to manage it in code.The sender gets 404 and nothing is logged
The sender gets 404 and nothing is logged
The URL is wrong or its token was rotated.
lua triggers list prints the current URL; a request that matches no trigger is not recorded.Next steps
LuaTrigger reference
The context object, every slot, statuses, and startWorkflow fields.
lua triggers reference
create, list, logs, activate, rotate-token, delete.
Handle a webhook
When you need your own handler and response.
Integration events
Route events from a connected SaaS to a trigger.

