Output
What you’ll build
- A
supportskill with two tools:lookup_orderreads an order fromData, andcreate_ticketwrites one. - An
order-statuswebhook that stores each order event solookup_orderhas something to find. - A persona in object form, with separate instructions for text channels and voice calls.
- Knowledge Search over documents you upload in the admin dashboard.
- A
daily-summaryjob that counts open tickets every morning. - A released agent version, embedded on a web page with the chat widget.
1
Code: Add a support skill with two tools
Both tools use The skill’s Register the skill beside the weather skill.Run Run
Data, the agent-scoped JSON store; collections (orders, tickets) are created on first write. Data.get takes the collection, a filter, a page number, and a page size, and returns { data, pagination }; each entry keeps your fields under data. lookup_order returns { found: false } instead of throwing, because the model reads the return value and the skill’s context tells it what to say when the order is missing.src/skills/tools/LookupOrderTool.ts
create_ticket writes an entry and returns its ID so the model can read it back to the end user. The zod describe() strings are part of what the model sees, so write them as instructions for filling the field.src/skills/tools/CreateTicketTool.ts
context tells the model when to call each tool and what to do with a miss.src/skills/support.skill.ts
src/index.ts
create_ticket once. lua test executes your code on your machine, but Data calls reach the platform, so the ticket is stored on the agent.Output
lookup_order for the same order. You should see found: false: nothing has written to orders yet, which the next step fixes.Output
2
Code: Store order events with a webhook
A webhook is an HTTP endpoint your code handles outside any conversation; no model runs. This one validates the body with zod (a request that fails Register it on the agent.Run In production, sign the calls: set
bodySchema is rejected before execute runs), then creates or updates the order’s entry so the same order number never gets two entries.src/webhooks/OrderStatusWebhook.ts
src/index.ts
lua test webhook takes the request as { "query", "headers", "body" } and runs execute with it.Output
lookup_order again. You should see the status the webhook stored.Output
secret on the webhook and send x-lua-signature; see Handle a webhook.3
Code: Write the persona for text and voice
The persona is the text the model reads before every conversation. In object form, Talk to the agent in the sandbox.
base is rendered on every channel, then text is appended on text channels and voice on voice calls. The skill context stays where it is: the persona says who the agent is, the context says when to call which tool.src/index.ts
lua chat -e sandbox compiles your code and uploads it as sandbox versions the platform runs; the first run after a new skill registers it on the server and may answer without it (Skipping skill support - no skillId found in lua.skill.yaml), so run the command twice. You should see the model call lookup_order and report the shipped status.Output
4
Dashboard: Add knowledge
Knowledge is the set of documents the agent retrieves from while the Knowledge Search feature (If it reads
rag) is on; it lives on the server, not in your code. Open the agent in the admin dashboard (lua admin opens it), select the Knowledge tab, and upload a document such as your returns policy. You should see the document in the tab’s list once its processing finishes. From the terminal, lua resources list prints the same list.rag retrieves passages from your uploads and puts them in front of the model when a question matches. lua init asks for every capability feature, so the agent normally starts with rag on; confirm from the terminal, where the first entry should read Active.Output
Inactive, turn it on with lua features enable --feature-name rag. Ask the sandbox agent a question the document answers, such as “What is your returns policy?”; it answers from the upload.5
Code: Schedule a daily summary job
A job runs on a schedule with no conversation attached, so there is no end user, no thread, and no model unless your code calls one. Register it; this is the agent’s final shape.
schedule is cron (with an optional IANA timezone), interval in seconds, or once at a date; timeout is in seconds. This one counts open tickets at 09:00 London time, stores the total, and returns it.src/jobs/DailySummaryJob.ts
src/index.ts
lua test job runs execute now instead of waiting for the schedule. You should see the ticket from step 1 counted.Output
6
Terminal: Release the agent
lua push all compiles, bumps the patch version of every primitive, uploads each one plus the persona and a source backup, and records the new versions in lua.skill.yaml. The skills, webhook, and job change nothing for end users until you promote; the persona is served from the next message. --force skips the confirmation, and --ci fails instead of prompting.Output
1 again would roll the code back. lua version list shows which version is active.Output
7
Code: Put the agent on your website
The web widget is the channel end users reach from a browser: one script tag, no build step, and it talks to the same promoted version as Open the page. You should see a chat button in the bottom-right corner, and “Where is order A-1001?” gets the same answer as
lua chat -e production. Set environment: "production" and replace agent_abc123 with the agentId in lua.skill.yaml.index.html
lua chat -e production. Colors, position, and welcome text are covered in the web widget quickstart.Ask production about the order. The answer comes from
lookup_order reading the entry your webhook wrote, under the new persona.Output
Remove the test records
Data is shared by the sandbox and production, so the ticket, order, and summary you created stay on the agent. There is no CLI command for entries; delete them from code with Data.delete(collection, entryId). Add this tool to the support skill, run it once with lua test, then remove it before your next push.
src/skills/tools/ClearTestDataTool.ts
What you learned
- A skill’s
contextplus each tool’sdescriptionis how the model decides when to call your code, andlua testruns a tool without a model (About skills and tools). Datais the agent-scoped store tools, webhooks, and jobs share, which is how a webhook can feed a tool (Datareference).- A webhook handles HTTP outside any conversation, and
lua test webhookreplays one request locally (About webhooks). - The persona’s object form gives text channels and voice calls different instructions on top of a shared
base, and a pushed persona is served at once (About persona). - Knowledge lives on the server and needs the
ragfeature; uploads and features are managed from the admin dashboard orlua features(About knowledge and features). - A job runs on a cron, interval, or one-time schedule;
lua test jobruns it immediately (About jobs). lua pushuploads,lua version createsnapshots, andlua version promotemakes a snapshot live or rolls back (About releases and versions).
Next steps
Handle a webhook
Sign requests with
secret, verify x-lua-signature, and make handlers idempotent.About execution contexts
What
User, Data, and env resolve to in a tool, a webhook, and a job.LuaAgent reference
Every field you can register on the agent, with types and defaults.

