Just a few weeks in the past, we introduced Dynamic Employees, a brand new function of the Employees platform which helps you to load Employee code on-the-fly right into a safe sandbox. The Dynamic Employee Loader API basically offers direct entry to the essential compute isolation primitive that Employees has been based mostly on all alongside: isolates, not containers. Isolates are a lot lighter-weight than containers, and as such, can load 100x sooner utilizing 1/10 the reminiscence. They’re so environment friendly, they are often handled as “disposable”: begin one as much as run a couple of traces of code, then throw it away. Like a safe model of eval().
Dynamic Employees have many makes use of. Within the unique announcement, we targeted on how one can use them to run AI-agent-generated code as a substitute for instrument calls. On this use case, an AI agent performs actions on the request of a consumer by writing a couple of traces of code and executing them. The code is single-use, meant to carry out one process one time, and is thrown away instantly after it executes.
However what in order for you an AI to generate extra persistent code? What in order for you your AI to construct a small utility with a customized UI the consumer can work together with? What in order for you that utility to have long-lived state? However in fact, you continue to need it to run in a safe sandbox.
A method to do that could be to make use of Dynamic Employees, and easily present the Employee with an RPC API that offers it entry to storage. Utilizing bindings, you might give the Dynamic Employee an API that factors again to your distant SQL database (maybe backed by Cloudflare D1, or a Postgres database you entry by Hyperdrive — it is as much as you).
However Employees additionally has a novel and very quick kind of storage which may be an ideal match for this use case: Sturdy Objects. A Sturdy Object is a particular form of Employee that has a novel identify, with one occasion globally per identify. That occasion has a SQLite database hooked up, which lives on native disk on the machine the place the Sturdy Object runs. This makes storage entry ridiculously quick: there’s successfully zero latency.
Maybe, then, what you actually need is to your AI to write down code for a Sturdy Object, and you then need to run that code in a Dynamic Employee.
This presents a bizarre downside. Usually, to make use of Sturdy Objects it’s important to:
Write a category extending
DurableObject.Export it out of your Employee’s major module.
Specify in your Wrangler config that storage ought to be provision for this class. This creates a Sturdy Object namespace that factors at your class for dealing with incoming requests.
Declare a Sturdy Object namespace binding pointing at your namespace (or use ctx.exports), and use it to make requests to your Sturdy Object.
This does not lengthen naturally to Dynamic Employees. First, there’s the plain downside: The code is dynamic. You run it with out invoking the Cloudflare API in any respect. However Sturdy Object storage needs to be provisioned by the API, and the namespace has to level at an implementing class. It might’t level at your Dynamic Employee.
However there’s a deeper downside: Even when you might one way or the other configure a Sturdy Object namespace to level instantly at a Dynamic Employee, would you need to? Would you like your agent (or consumer) to have the ability to create a complete namespace filled with Sturdy Objects? To make use of limitless storage unfold all over the world?
You most likely do not. You most likely need some management. It’s possible you’ll need to restrict, or at the least monitor, what number of objects they create. Possibly you need to restrict them to only one object (most likely ok for vibe-coded private apps). It’s possible you’ll need to add logging and different observability. Metrics. Billing. And so on.
To do all this, what you actually need is for requests to those Sturdy Objects to go to your code first, the place you’ll be able to then do all of the “logistics”, and then ahead the request into the agent’s code. You need to write a supervisor that runs as a part of each Sturdy Object.
Resolution: Sturdy Object Sides
Immediately we’re releasing, in open beta, a function that solves this downside.
Sturdy Object Sides let you load and instantiate a Sturdy Object class dynamically, whereas offering it with a SQLite database to make use of for storage. With Sides:
First you create a traditional Sturdy Object namespace, pointing to a category you write.
In that class, you load the agent’s code as a Dynamic Employee, and name into it.
The Dynamic Employee’s code can implement a Sturdy Object class instantly. That’s, it actually exports a category declared as
extends DurableObject.You’re instantiating that class as a “facet” of your personal Sturdy Object.
The aspect will get its personal SQLite database, which it could possibly use by way of the traditional Sturdy Object storage APIs. This database is separate from the supervisor’s database, however the two are saved collectively as a part of the identical general Sturdy Object.
Right here is an easy, full implementation of an app platform that dynamically hundreds and runs a Sturdy Object class:
import 0;
++counter;
this.ctx.storage.kv.put("counter", counter);
return new Response("You've made " + counter + " requests.n");
from "cloudflare:workers";
// For the aim of this instance, we'll use this static
// utility code, however in the true world this is likely to be generated
// by AI (and even, maybe, a human consumer).
const AGENT_CODE = `
import 0;
++counter;
this.ctx.storage.kv.put("counter", counter);
return new Response("You've made " + counter + " requests.n");
from "cloudflare:workers";
// Easy app that remembers what number of instances it has been invoked
// and returns it.
export class App extends DurableObject {
fetch(request)
// We use storage.kv right here for simplicity, however storage.sql is
// additionally obtainable. Each are backed by SQLite.
let counter = this.ctx.storage.kv.get("counter")
}
`;
// AppRunner is a Sturdy Object you write that's accountable for
// dynamically loading purposes and delivering requests to them.
// Every occasion of AppRunner accommodates a special app.
export class AppRunner extends DurableObject {
async fetch(request) {
// We have acquired an HTTP request, which we need to ahead into
// the app.
// The app itself runs as a toddler aspect named "app". One Sturdy
// Object can have any variety of sides (topic to storage limits)
// with totally different names, however on this case we've just one. Name
// this.ctx.sides.get() to get a stub pointing to it.
let aspect = this.ctx.sides.get("app", async () => {
// If this callback is named, it means the aspect hasn't
// began but (or has hibernated). On this callback, we are able to
// inform the system what code we wish it to load.
// Load the Dynamic Employee.
let employee = this.#loadDynamicWorker();
// Get the exported class we're curious about.
let appClass = employee.getDurableObjectClass("App");
return { class: appClass };
});
// Ahead request to the aspect.
// (Alternatively, you might name RPC strategies right here.)
return await aspect.fetch(request);
}
// RPC technique {that a} shopper can name to set the dynamic code
// for this app.
setCode(code) {
// Retailer the code within the AppRunner's SQLite storage.
// Every distinctive code will need to have a novel ID to move to the
// Dynamic Employee Loader API, so we generate one randomly.
this.ctx.storage.kv.put("codeId", crypto.randomUUID());
this.ctx.storage.kv.put("code", code);
}
#loadDynamicWorker() {
// Use the Dynamic Employee Loader API like regular. Use get()
// moderately than load() since we might load the identical Employee many
// instances.
let codeId = this.ctx.storage.kv.get("codeId");
return this.env.LOADER.get(codeId, async () => {
// This Employee hasn't been loaded but. Load its code from
// our personal storage.
let code = this.ctx.storage.kv.get("code");
return {
compatibilityDate: "2026-04-01",
mainModule: "worker.js",
modules: { "worker.js": code },
globalOutbound: null, // block community entry
}
});
}
}
// This can be a easy Employees HTTP handler that makes use of AppRunner.
export default {
async fetch(req, env, ctx) {
// Get the occasion of AppRunner named "my-app".
// (Every identify has precisely one Sturdy Object occasion within the
// world.)
let obj = ctx.exports.AppRunner.getByName("my-app");
// Initialize it with code. (In an actual use case, you'd solely
// need to name this as soon as, not on each request.)
await obj.setCode(AGENT_CODE);
// Ahead the request to it.
return await obj.fetch(req);
}
}
On this instance:
AppRunneris a “normal” Sturdy Object written by the platform developer (you).Every occasion of
AppRunnermanages one utility. It shops the app code and hundreds it on demand.The applying itself implements and exports a Sturdy Object class, which the platform expects is known as
App.AppRunnerhundreds the applying code utilizing Dynamic Employees, after which executes the code as a Sturdy Object Side.Every occasion of
AppRunneris one Sturdy Object composed of two SQLite databases: one belonging to the father or mother (AppRunneritself) and one belonging to the aspect (App). These databases are remoted: the applying can’t learnAppRunner‘s database, solely its personal.
To run the instance, copy the code above right into a file employee.js, pair it with the next wrangler.jsonc, and run it domestically with npx wrangler dev.
// wrangler.jsonc for the above pattern employee.
{
"compatibility_date": "2026-04-01",
"main": "worker.js",
"migrations": [
{
"tag": "v1",
"new_sqlite_classes": [
"AppRunner"
]
}
],
"worker_loaders": [
{
"binding": "LOADER",
},
],
}
Sides are a function of Dynamic Employees, obtainable in beta instantly to customers on the Employees Paid plan.
Try the documentation to be taught extra about Dynamic Employees and Sides.



