- A project created with
lua initand signed in withlua auth configure(Install and sign in). Local runs still need a credential and the project’s agent ID. - Sandbox secrets in
.env, set withlua env sandbox -k <KEY> -v <value>.lua testloads.envinto the run; see thelua envreference.
1
Run one tool with exact input
lua test skill compiles the project, then calls the tool’s execute function directly in a local runtime. No model is involved, so the output is exactly what the tool returns. --name is the tool name, not the skill name, and --input is the tool’s own input fields.Output
Data, User, Channels) go to the real API under your credential. A tool that throws does not fail the command: the run still prints ✅ Tool execution successful!, exits 0, and shows { status: 'error', error: '<message>' } as the output, so check the output rather than the exit code (with --json: jq -e 'type != "object" or .status != "error"'). A run that ends with Tool "<name>" not found means you passed the skill name; run lua test skill with no flags to pick from the compiled tool list.2
Run a webhook, job, or processor the same way
The other A preprocessor run prints the action and the processed messages (
lua test types take the shape their primitive receives. A webhook gets query, headers, and body; a job takes no input; a preprocessor gets message and channel; a postprocessor gets message, response, and channel.Output
Action: PROCEED, then 1. [TEXT] Call me on [phone] or mail [email]); a postprocessor run prints Processed response: followed by the modified text. The webhook’s secret is not checked here: the platform verifies signatures only on incoming requests.3
Talk to the agent in the sandbox
lua chat -e sandbox compiles your project, uploads the compiled skills and processors as sandbox versions, and sends your persona with each message; the platform runs them against the model, so no lua push is needed and production is untouched. Pass -t with no value to get a fresh, isolated thread whose ID is printed as ℹ️ Thread: <id>; add --clear to delete that history when the command exits.-t, the message lands in your default thread and earlier turns shape the answer. Without -e, lua chat -m defaults to the sandbox and says so. Sandbox chat reads the same .env as lua test: lua env sandbox -k <KEY> -v <value> writes only that file, there is no server-side sandbox variable store, and lua chat -e sandbox uploads the file’s values with the sandbox versions it compiles, so your tools run on the platform with them. Production reads the variables set with lua env production.4
Run a workflow offline
lua test workflow drives a workflow locally on a virtual clock. Agent steps are faked by default (--agents fake answers [fake:<stepId>] … plus a schema-shaped object); tool steps need --step-output <stepId>=<json> or recorded --fixtures <dir>; approvals are pre-answered with --approve <stepId> or --deny <stepId>.AI.generate, Channels.send, Data) run for real against the API. Pass --agents live to call the model for agent steps too. The complete driver is on Test a workflow offline.5
Run voice tests
lua voice test runs every *.voice.test.ts file in the project with Jest or Vitest, whichever the project has installed; --voice <name> limits the run to <name>.voice.test.ts.lua voice reference.6
Verify production after a release
Once a version is live, send one message to production on a fresh thread, then confirm that no An empty
agent_error entry and no skill entry with subType error were written; a throwing tool is logged under skill. The time-bounded form of this check is in Release an agent to production.Output
logs array is the pass condition. Anything else: read the entries with Read logs and debug an agent.Options you may need
Script the output
Add--json to any lua test type to get the raw return value on stdout with progress on stderr, so lua test skill --name lookup_tickets --input '{"customerEmail":"[email protected]"}' --json | jq length works. lua logs --json returns { logs, pagination }.
Let a coding agent run the ladder
The Claude Code plugin’s/lua-qa command runs compile, lua test, and a sandbox conversation, then reports what failed; see Claude Code plugin.
If it isn’t working
✖ not_found: Tool "<name>" not found
✖ not_found: Tool "<name>" not found
Exit code 3.
--name received a skill name or a misspelled tool name. Tool names are the name property of the class, for example lookup_tickets; run lua test skill without flags to see the compiled list.✖ usage: Invalid JSON input: …
✖ usage: Invalid JSON input: …
Exit code 2. The
--input string is not valid JSON. Wrap it in single quotes so the shell leaves the double quotes alone, and pass the tool’s fields directly, without a {"tool": …} envelope.✖ error: No supported test runner found.
✖ error: No supported test runner found.
lua voice test needs Jest or Vitest in the project. Install one (npm install -D vitest) and re-run; --runner jest or --runner vitest forces the choice.Next steps
Release an agent to production
Push, version, promote, verify, and roll back.
Read logs and debug an agent
Filter
lua logs and run the debug loop.lua test reference
Every type, flag, and exit code.
About environments
What the sandbox shares with production.

