Run Environment
When your tool runs on Rival, it executes in a managed, isolated environment created just for that run. Understanding what this environment looks like helps you write handlers that behave predictably and stay within the platform’s limits.
Isolation
Every run runs in its own isolated environment. There’s no shared memory between runs - not between two calls to the same tool, and not between different tools in the same organization. Each invocation starts clean.
That means you can’t use in-memory variables, module-level state, or global caches to persist data between runs. If your tool needs to remember something across calls, it has to read and write from an external store. See Storage.
The isolation extends both ways: nothing one run does can affect another run, and nothing another run does can leak into yours. This makes runs safe to scale horizontally without coordination.
Ephemeral filesystem
The filesystem inside the run environment is ephemeral. Your handler can write temporary files to disk during a run - and that’s fine for scratch work - but everything is wiped when the run ends. The next run starts with a fresh filesystem.
For persistent file access, use Digital Assets. Each asset has a stable path your handler can read at runtime, and it’s the same path on every run.
Resource limits
Each run has access to a fixed set of resources:
| Resource | Limit |
|---|---|
| Memory | 512 MB |
| Timeout | 300 seconds |
| CPU | 2.0 cores |
These limits are per run. If your handler exceeds the timeout, the run is terminated and the caller receives a 408 response. Memory overruns also terminate the run. Design your handlers to finish within these bounds - if you’re doing heavy processing, consider splitting the work into multiple runs or offloading the expensive parts to an external service.
No shared state between runs
To be explicit: anything that lives at module scope, in process memory, in a global variable, or on the local filesystem does not persist between runs. Even if two consecutive runs of the same tool happen to land in the same execution environment, you can’t rely on it.
This is the single most common surprise when building on Rival. Treat each run as a fresh start.
If you need state:
- Files that should persist - upload to Digital Assets.
- Structured data that changes at runtime - connect to an external database (Postgres, Redis, MongoDB, Supabase, etc.) over the network.
See Storage for the full picture.
Environment variables / Secrets
Environment variables defined in your workspace are injected into the run environment. Your handler reads them using the standard mechanism for its language - os.environ in Python, process["env"] in Python 3.13 — Fast, process.env in JavaScript, os.getenv in Lua.
Environment variables are set in the Settings option found at the bottom left of the left sidebar → Secrets, and assigned to specific tools from the tool’s edit/create flow. They’re the right place to store API keys, endpoint URLs, and other configuration that shouldn’t be hardcoded.
Network access
Tools have outbound network access. Your Python handler can make HTTP requests to external APIs, connect to a database, fetch a file - whatever you need. The Lua runtime is synchronous and doesn’t have practical I/O primitives, so network calls aren’t viable from it.
Runtime-specific notes
Python 3.13
Packages listed in requirements.txt are installed before your handler runs. On a cold start there’s a brief install cost; subsequent runs in the same environment skip it.
Main file: cortexone_function.py. Entry point: cortexone_handler(event, context).
def cortexone_handler(event, context): name = event.get("name", "world") return { "statusCode": 200, "body": {"message": f"Hello, {name}!"} }Python supports async I/O, so you can use HTTP clients, database drivers, and other I/O-bound libraries normally.
JavaScript (V8)
async/await and Promises are supported for synchronous operations (storage, computation, fetch). setTimeout, setInterval, and external event-driven APIs are not supported. No package manager.
Main file: cortexone_function.js. Entry point: cortexone_handler(event, context).
function cortexone_handler(event, context) { const name = event.name || "world"; return { statusCode: 200, body: { message: `Hello, ${name}!` } };}Lua
Synchronous, sandboxed standard library, no package manager. Best for lightweight, deterministic computation.
Main file: cortexone_function.lua. Entry point: cortexone_handler(event, context).
function cortexone_handler(event, context) local name = event.name or "world" return { statusCode = 200, body = { message = "Hello, " .. name .. "!" } }endRelated
- How Runs Work - the request lifecycle around the run environment
- Storage - what to do when you need state across runs
- Runtime - the three runtimes you can pick from