Skip to content

Build1 publisher2 min readPublished Updated

Vercel puts agent-written TypeScript in QuickJS and makes host functions the real boundary

The Run SDK swaps eval's ambient authority for a worker-thread sandbox with narrow host functions and resumable interrupts. The replay semantics are the part to read twice.

The Engineer · Build desk

What happened

  • Vercel shipped the Run SDK, a package for executing untrusted JavaScript and TypeScript without handing it access to the surrounding application or system.
  • Code is evaluated in a fresh QuickJS context inside a worker thread, with no direct route to Node.js or the network.
  • Applications expose named host functions as sandbox globals, so a program can call store.listOrders() while the database client and its credentials stay outside.
  • An interrupted run returns a signed token the application saves with the approval request and later uses to resume the run.
  • The same package is the internal module behind code mode tool execution in the AI SDK.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • constraint Any host function that writes and can be in flight when an approval fires needs an idempotency key, because replay will not have a recorded result for it.
  • decision Tool granularity stops being an ergonomics question: each host function you name is where the user and resource check has to live, so a catch-all request helper is now a security choice you have...
  • cost The saving is model context and token spend, paid for in host-function plumbing that someone has to write and review per product action.
  • exposure The signed resume token is an authorization to finish a privileged program that already cleared a human, which puts it on the list of secrets your approval queue now stores.

What `eval` actually hands a generated program is ambient authority. Vercel's framing is that evaluated code gets the same access as the application around it, secrets and internal services included, with no durable way to pause at the points where an auth check or a human should intervene [2]. The QuickJS interpreter is the advertised fix, but the boundary doing the work is serialization: calls leave the sandbox as serialized values, and a host function may return a promise, so an existing service client sits behind the interface rather than being passed across it [5].

The resumption contract deserves a slow read. Replay is how a resumed run gets back to where it stopped. The program body runs again, and settled host function calls return their recorded results instead of repeating the work [8]. A run with one approval gate therefore executes its program body twice, once up to the interrupt and once after the decision [15]. The memoization covers only calls that had settled, which means a call still in flight when the interrupt fires has no recorded result and executes a second time on resume [9]. That is a property of the design rather than a defect in it, and it decides which host functions can safely sit next to an interrupting one.

The interrupt itself is a call inside the host function: read the context, and if no resume value is present, raise an approval with a message [6]. That is a sound shape, and it also marks what the sandbox declines to do. It governs what the program can reach, not whether reaching is correct. Vercel concedes as much in recommending `orders.refund(id)` over a generic request function, on the grounds that the specific function gives the application a clear place to check the user and the order [10]. A program written under the influence of a hostile document is inside the boundary the moment it calls a function you chose to expose. What stands there is the check you wrote, plus a person for the expensive operations.

The efficiency case is separate from the security case and will probably close faster. One model response can carry several calls and the logic joining them, two lookups run concurrently, filtering stays inside the program, and only the result returns [12]. Vercel's example is a support agent inspecting an account without the entire billing response landing back in its context [13].

The playground is the honest summary: code you run there can reach only the host functions on that page [14]. Everything this buys you is the size of that list.

What to watch

  • Whether Vercel publishes per-run execution limits (CPU, memory, wall clock) and an expiry policy for interrupt tokens.
  • Whether the docs specify what happens to values that cannot survive the serialization boundary, such as streams or open handles.
  • Whether code mode becomes the default tool path in the AI SDK, which would make this sandbox the boundary for teams that never chose it.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories