A spreadsheet that fetches the world.
An external function is just a function. You write FX_RATE("USD","EUR") the way you write SUM(...). Behind the scenes, Grid queues a worker job, tracks a status lifecycle, caches the result, and writes back to your cell — while the rest of the model keeps computing.
Five external functions, built in.
Each ships with a default cache TTL, a default timeout, and a worker route. Tier 1 deployments register Python-backed functions through a model-host manifest; from inside a cell they look identical to the built-ins.
One token, four steady states, two terminal-ish branches — stale on a newer revision and failedwhen an attempt didn't land.
Every external value has a status.
dirty → queued → running → ready on the happy path. stale when a newer revision is desired. failedwhen the latest attempt didn't land. Read it through the API or stream it over the websocket.
Pair the call with DEFAULT and the rest of the model keeps computing while the cell rides the lifecycle. Use ?= to write only on success — a transient failure won't blank a previously good value.
One operator decides when work happens.
= queues the work the moment the model deploys. ~= waits until something reads the cell. Same syntax everywhere else — but a single character chooses between a warm dashboard at deploy time and a cold pool of cells that fire only when asked.
Eager — at deploy
Worker starts immediately. Downstream cells use DEFAULT until ready. Best for hot paths and live dashboards.
Lazy — on demand
No work until something asks. Eliminates the "deploy creates a thundering herd of jobs" problem. Best for rare-read or expensive paths.
Each external call lowers to a deterministic synthetic symbol — so a cell that wraps FX_RATE in ROUND is cached at the boundary, not at the outer expression. One fetch, many reads.
The cell is the wire. The world is the value.
# eager: warm at deploy B7 = FX_RATE("USD", "EUR") last_good ?= B7 rate = last_good DEFAULT 1.08 # lazy: only when read P1 ~= ML_SCORE(features) risk = P1 DEFAULT 0 # defensive multi-step user_email = WITH u = HTTP_JSON("https://api.x/me"), THEN u.email ELSE "unavailable"