Execute Lua code in a sandboxed environment.
Uses tv-labs/lua (Luerl), a pure Erlang Lua implementation. Provides:
- CPU limits via timeout
- Memory limits via process heap limits
- Host callbacks for safe interaction with your application
- Complete crash isolation (pure Erlang, no NIF)
Usage
# Simple eval
{:ok, result} = Puck.Sandbox.Eval.Lua.eval("return 1 + 2")
# => {:ok, 3}
# With callbacks
{:ok, result} = Puck.Sandbox.Eval.Lua.eval("""
local products = search_products("laptop")
local cheap = {}
for _, p in ipairs(products) do
if p.price < 1000 then table.insert(cheap, p) end
end
return cheap
""", callbacks: %{
"search_products" => &MyApp.Products.search/1
})
# With resource limits
{:ok, result} = Puck.Sandbox.Eval.Lua.eval(code,
callbacks: %{...},
timeout_ms: 5_000,
max_heap_words: 1_000_000
)Requirements
Requires the lua package: {:lua, "~> 0.4.0"}
Options
:callbacks- Map of callback names to functions (e.g.,%{"name" => &Mod.fun/1}):timeout_ms- Execution timeout in ms (default: 5_000):max_heap_words- Memory limit in words (default: 1_000_000, ~8MB on 64-bit)
Safety
Luerl sandboxes by default, blocking:
iomodule (file I/O)os.execute,os.exit,os.getenv,os.remove,os.rename,os.tmpnameload,loadfile,loadstring,dofile,requirepackagemodule
The only risk is user-provided callbacks.
Summary
Functions
Evaluates Lua code in a sandboxed environment.
Like eval/2 but raises Puck.Sandbox.Eval.Lua.Error on failure.
Returns a Zoi schema for the ExecuteCode struct.
Functions
Evaluates Lua code in a sandboxed environment.
Returns {:ok, result} on success or {:error, reason} on failure.
Examples
{:ok, 3} = Puck.Sandbox.Eval.Lua.eval("return 1 + 2")
{:ok, result} = Puck.Sandbox.Eval.Lua.eval("""
local x = 0
for i = 1, 100 do x = x + i end
return x
""")
# => {:ok, 5050}
{:error, :timeout} = Puck.Sandbox.Eval.Lua.eval("while true do end", timeout_ms: 100)
Like eval/2 but raises Puck.Sandbox.Eval.Lua.Error on failure.
Examples
3 = Puck.Sandbox.Eval.Lua.eval!("return 1 + 2")
Returns a Zoi schema for the ExecuteCode struct.
The schema includes guidance in the code field description to help LLMs
generate valid Lua code (e.g., always use return to return values).
Arguments
func_spec- A Zoi schema describing the available callback functions. The LLM will see this schema and understand what functions it can call.
Example
@func_spec Zoi.object(%{
name: Zoi.enum(["double", "search"]),
description: Zoi.string()
}, strict: true, coerce: true)
schema = Zoi.union([
Puck.Sandbox.Eval.Lua.schema(@func_spec),
Zoi.struct(Done, %{type: Zoi.literal("done"), message: Zoi.string()}, coerce: true)
])
# Pattern match on the struct:
case action do
%Puck.Sandbox.Eval.Lua.ExecuteCode{code: code} ->
Puck.Sandbox.Eval.eval(:lua, code, callbacks: callbacks)
%Done{message: msg} ->
{:ok, msg}
end