Agents.invoke or Channels.send). They differ in what starts them, whether a conversation is involved, how you test them, and how they go live. Picking the wrong one is the most common reason a task feels harder than it should: a webhook that chains three tools by hand wanted to be a workflow, and a job that loops over end users wanted to be a dynamic job per end user.
Verified against lua-cli 3.33.0.
The eight ways compared
Three rules explain most of the table.
lua test runs one primitive’s execute on your machine with the input you give it and no model; only skills, webhooks, jobs, processors, and workflows have a test type, so a trigger or an MCP server is exercised on the live agent. A sandbox lua chat swaps in your local skills, processors, and persona, and uses whatever webhooks, jobs, triggers, workflows, and MCP servers are already live. And every code primitive except an MCP server is versioned: lua push uploads a version, lua version create snapshots the agent, and lua version promote makes the snapshot live for every primitive at once. lua deploy <type> is the single-primitive shortcut: it goes live at once for webhooks, jobs, preprocessors, postprocessors, and triggers by creating and promoting an agent version scoped to that primitive, and lua workflows deploy does the same for a workflow; lua deploy skill --set-version <v> serves that skill version from the agent’s next turn on any agent, but the next lua version promote resets every skill to the promoted agent version’s pin, so make a skill change durable with lua version create and promote (releases and versions). The persona is not a primitive and is made live by push: a pushed persona is served from the agent’s next message, and lua deploy persona switches it to an earlier version at once.
A decision path
Two refinements. If the event comes from a SaaS you connected through Unified.to, subscribe to it with an integration webhook and point it at a webhook or a trigger rather than building the intake yourself. If you only need one model call inside code, with no persona and no tools, callAI.generate instead of Agents.invoke; see Compose agents.
Common combinations
- Trigger into a workflow with an approval. The vendor posts to the trigger URL,
transformreturns{ startWorkflow }, and the run pauses on.approval()until a person decides. SetidempotencyKeyfrom the vendor’s delivery ID; otherwise every redelivery starts another run. - Webhook plus job. The webhook records each event in
Dataas it arrives; a nightly job aggregates the day and sends the summary withChannels.send. - Tool plus dynamic job. The tool creates a job with
schedule: { type: 'once' }and puts everything it needs inmetadata, becauseexecuteis serialized and can’t close over variables. When it fires,job.user()returns the end user who asked. - Tool plus preprocessor for human handoff. The tool sets a flag on the end user; a preprocessor returns
{ action: 'block' }while the flag is set and notifies a person withChannels.send. See Add human handoff. - Webhook into
Agents.invoke. When an HTTP event needs a model decision but the sender expects a specific response body, verify and answer in the webhook, then invoke the agent with the end user’suserId.
Next steps
Add a tool
Write a tool, register its skill, and test it with
lua test skill.Handle a webhook
Sign, verify, and handle an HTTP event idempotently.
Schedule a job
Run code on a schedule, then push and deploy it.
Workflows quickstart
Build a run with an approval step and test it offline.

