fetch, and returns a result the model can use, or a clear error when it can’t. The pattern fits any HTTP service; when the service is one of Lua’s integrations, connect it instead and skip the key handling.
Verified against lua-cli 3.33.0.
Before you begin
- A tool registered in a skill on the agent (Add a tool to a skill).
- The API’s base URL and a key for it.
1
Store the key for local runs
lua env sandbox writes the project’s .env file. lua test loads it before it runs your code, and lua chat -e sandbox uploads its values with each sandbox version, so sandbox turns read them from the platform..env from its key-value pairs, so don’t keep hand-written comments in it. Add .env to .gitignore; the scaffold doesn’t.2
Call the API from execute
env('KEY') returns the value or undefined. Read what you need at the top, fail fast with a message the model can relay, and bound the wait with a timeout well under the tool’s budget.src/skills/tools/GetOrderStatusTool.ts
3
Run it locally
lua test runs execute on your machine with the values from .env and no model in the loop.Output
{ status: 'error', error: 'fetch failed' } after the stack trace; a thrown message appears as error the same way.4
Store the key for production
Production code reads only the agent’s server-side environment;
.env is read by lua test and uploaded with sandbox versions, and never reaches production (About environments). Set the values once; no push or deploy is needed, and a changed value applies on the next call.lua env production --list prints the keys with values masked after the first four characters; the masking is display-only, and the interactive lua env production menu shows a variable’s full value to any credential holding knowledge:read. To rotate a key, set the replacement value and revoke the old one at the provider.5
Release
Push uploads a skill version and changes nothing for end users; the agent version you create and promote is what goes live, and it is also the rollback path.
lua version create prints ✓ Created v<n> (staged). Run `lua version promote v<n>` to deploy.; <n> comes from that line, promote accepts <n> or v<n> and asks no confirmation, and in a script n=$(lua version list --limit 1 --json --ci | jq -r '.[0].version') reads it. lua deploy skill --set-version <v> serves that version from the agent’s next turn, but the next lua version promote resets the skill to the promoted agent version’s pin; push, create, and promote for a durable change. See Release an agent to production.6
Verify
Ask the live agent and read the tool’s log. The reply quotes the status and carrier; the log’s
Tool result line holds the object the tool returned, or the error it threw.--name on lua logs is the name of the skill that holds the tool. A Tool result { status: 'error', … } with ORDERS_API_URL and ORDERS_API_KEY are not set means the production environment is missing a key.Options you may need
Retry a failed request
Retry only requests that are safe to repeat: aGET, or a POST that carries an idempotency key your API honors. Retry once or twice with a short wait, only on a timeout or a 5xx status, and keep the total under the 180-second tool budget; a 4xx is your bug or the end user’s input and won’t change on retry. Never retry a write that has no idempotency key, because the first attempt may have succeeded.
Send a body
Passmethod: 'POST', a Content-Type: application/json header, and body: JSON.stringify(payload). The same timeout and status checks apply.
If it isn’t working
The production reply says the API key is not set, but lua test works
The production reply says the API key is not set, but lua test works
lua test and sandbox chat read .env; production reads only the server-side map. Set the key with lua env production -k <KEY> -v <value> and send the message again.lua test prints { status: 'error', error: 'fetch failed' }
lua test prints { status: 'error', error: 'fetch failed' }
The host didn’t answer: wrong
ORDERS_API_URL, DNS, or a service that isn’t running. The cause is in the stack trace printed before the result. Deployed code can’t reach private-network addresses (execution contexts).Next steps
Environments
What .env, the sandbox, and production each read.
Store and search data
Cache or record what your API returned.
lua env reference
Every flag, masking, and the environment aliases.
env reference
Reading variables and the template form for workflows.

