Will ChenWill Chen
← writing

A shared runtime for concurrent agentsThe November and December 2025 framework experiments that put shared state, concurrent agents, and a live interface inside one application model.

system design4 min

Building Idyllic - Prior Iterations

November-December 2025

By November 2025, I wanted to make an AI application that could keep working on a shared task while a person watched, intervened, and returned to it later. A chat endpoint could receive a message and stream a reply. The application also needed somewhere to keep its documents, current work, and progress, together with operations that could change them.

I started Idyllic v4 with a basic working chat so I could exercise the whole path from the browser to the model and back. The next step was to put an application model behind that endpoint. I wanted to test its behavior in code while the components were still easy to change, then design the visual builder around the resulting mechanics.

One component was a module: a configured resource with its own state and operations. A document collection would provide both a place to keep documents and the methods for working with them. A messaging module would bring the conversation data needed by its functions. The plan was for an agent application to compose those resources without requiring its author to assemble a separate storage system for every capability.

One object for the session

The other question was what should own the state of the application itself. By December, I was working with a TypeScript class. A class describes an object through its properties and methods. That gave me a familiar way to express a running session: properties for its current state, methods for the things a person or another program could ask it to do.

Several agents could work inside that session. Each could have its own prompt and context while reading and updating a shared document or task board. I did not need a separate network service for every agent to express that coordination. Ordinary functions, variables, and promises were enough to describe the arrangement in code.

Compiling the application into a running system

A development sketch connects a Next.js application and idyllic source directory to bundling, script upload, a routing table, and a dispatcher worker. Red notes mark open implementation questions.
Deployment sketch from my Durable Objects research notebook, captured December 26, 2025. Red annotations mark open questions.

The December 26 sketch traces how that code might become something a browser could use. The application has an idyllic/ directory beside its frontend. A deployment command bundles the server code, uploads it, and records where requests should go. The browser connects to the resulting application through Idyllic's routing layer. The red annotations are questions I was still resolving, including where to build the bundle and how the live connection should pass through the system.

I was building on Cloudflare Workers and Durable Objects, with one stateful object representing a session. The research prototype helped me distinguish the object I wanted to write from the machinery needed to run it. Important state still had to be stored and restored; an ordinary in-memory property was not enough to make it durable. Idyllic's job was to connect that storage and synchronization behavior to the application's source model.

The source transform became central. I wanted the author to write a TypeScript class while Idyllic generated the worker and stateful-object code around it. By December 29, I had a prototype that transformed system.ts, connected to a React interface, and supported multiple parallel streams. Changes to synchronized fields on the server appeared in the browser as the work progressed. The more detailed account of that model is in Idyllic v4.

Streaming required more than a changing string. The interface needed to know which output was receiving text, whether an operation was still running, and when it had finished. A research application could have an explorer, a critic, and a synthesizer working through their own outputs while the session retained their common state. This gave me a concrete reason to define fields, actions, and completion behavior together.

Testing a shared task board

The Virtual Office prototype shows two tasks in progress, a documentation task in the backlog, and generated work from simulated employees Alice and Bob beside an activity log.
December 29, 2025: Virtual Office running demonstration tasks. The task board and each simulated employee's generated work are visible together. Still from my development recording.

Late on December 29, I chose a Virtual Office as another test application. It gave the runtime a small shared world to manage. A task board sat beside two simulated employees, Alice and Bob. Each had a current assignment and a panel showing generated work. An activity log recorded changes across the whole office.

The first capture shows two tasks in progress: a login form and a landing page. A documentation task remains in the backlog. These were demonstration tasks. I was testing whether several concurrent activities and the state they shared could remain visible through one application.

The board also provided a place for human review. A task could move into review, receive feedback, and return to work. That interaction needed to change the same state the agents used. Otherwise, the board would only illustrate a process running elsewhere, and a person's intervention would have no reliable connection to the next operation.

A later Virtual Office view shows one task done, one in review, and one in progress. Alice and Bob are taking breaks, while the activity log records task feedback and state changes.
Later in the same December 29 recording: tasks have moved between work, review, and completion. The energy bars and breaks are behavior of this test application, not measures of model performance.

In the later capture, the documentation task is marked done, the landing page is in review, and the login form is back in progress. Both simulated employees are taking a break. Their energy indicators were part of the toy office's behavior, not measurements of model capability. What mattered for the framework was that task status, generated output, and activity could be shown together as the application changed.

The same connection also helped with debugging. A coding agent could call the running system through its remote interface while I watched the browser update. Both were clients of the same session. The application did not need a second, separate representation just to make the test visible.

These prototypes exercised the stateful runtime and its connection to the interface. The larger module ecosystem, session access, and support for more complex application patterns still needed work. I now had a way to investigate them by writing small applications with specific shared state, actions, and visible results, while keeping the deployment and synchronization code inside the framework.


Series index

Previous: A language for AI applications