Architecture

One log, two readings

Four mechanisms carry the whole system: one door the browser talks through, a step loop that never grows, an append-only log the history is derived from, and a cycle that turns a finished run into a better component. Everything else is a capability plugged into those.

01Layers

Four layers, and the direction of dependency is strict: a capability never reaches up into the loop, and the loop never imports a specific capability. That is what makes a capability replaceable without touching anything else.

AgentEvolver layers, from browser to capabilities Browser React · one WebSocket /ws Gateway versioned command surface Runtime agent · session · trace memory · model tool atomic callables skill SKILL.md + scripts environment stateful, has actions connector MCP servers workflow HTML → program agent dispatched as a callable Where work happens sandbox · terminal · kernel · job · ssh tools act here · environment actions act on their own machine — no argument moves a tool between the two — Append-only session log trace → trajectory → training records · nothing is deleted, only shadowed
Dependencies point one way. The runtime knows the capability registries; no capability knows the runtime. The ordinary tools act on the local sandbox, always; work on another machine goes through that environment's own actions, so one step cannot read here and execute there while looking like a single coherent task.

02The one door

The browser reaches the runtime through a single WebSocket and nothing else — not a second port, not a direct call into a manager. Live views that need another protocol, such as a terminal or a VNC screen, are relayed through the gateway rather than exposed beside it.

Why

Because the browser is usually not on the machine the gateway runs on. One door means one forwarded port; an address that leaks — a container's ephemeral VNC port, a sandbox upstream — is an address that works on the developer's laptop and nowhere else.

A command is {id, method, params, protocol_version}. The version is checked before the method is looked up, so a newer client cannot half-succeed against an older server.

03The step loop

One step is: assemble what the model sees, ask it, dispatch what it asked for, record what came back. The loop itself does not grow — new behaviour attaches to the points marked below rather than adding a branch here.

One step of the agent loop Assemble prompt · memory tools · context Ask the model stream → reasoning + tool calls Dispatch permission → flush → run → observe Record trace · memory usage · trajectory next step, unless the model called done_tool or a budget stopped it pre-step hooks reminders · plan mode pre / post action permission · guards budgets step · token · wall
The dashed arrows are extension points, not calls the loop makes to named features. A reminder, a plan-mode gate, and a permission policy all attach at the same three places; none of them appears in the loop's own code.
Trap

"Dispatch" includes a step that looks like bookkeeping and is not: before a tool that may change anything, the log is flushed to disk. Events are queued, so the log trails the run — and a run killed inside that lag leaves no record of the command it was about to execute.

04The log, and its two readings

Everything a run does is appended to one log and nothing is ever deleted. But what the model's history says does shrink — compaction folds a run of records into a single summary. Those two facts are reconciled without losing anything: each event declares how it joins the history.

The append-only log and the two ways it is read append-only log — write order, never rewritten e0 e1 e2 e3 e4 · summary replaces e1–e3 e5 what the model is sent — replacements shadow what they stand for e0 e4 e5 3 messages what a person is shown — every turn they already read e0 e1 e2 e3 e5 5 turns · the summary is not one of them
One log, two projections. Reading the model's view to render a conversation is the mistake this distinction exists to prevent — it deletes turns the user has already read, the moment a summary lands, and it renders perfectly until then.

05The evolution cycle

A finished run is not only an answer. It is a reward-annotated record of what was tried, and that record is what a later round improves a component from. The cycle is deliberately gated at every point where a bad component could reach the next session.

From a run to a promoted component, and the gates in between Run agent does the task Trajectory steps + reward Generate a new component version Smoke gate real loop, synthetic task passes Promote archive first, then manifest fails Roll back or unload if brand-new the next run uses it — and produces the trajectory that judges it
Archiving happens before the manifest is written, so a rollback target exists before the change is live. A component that cannot be rolled back is unloaded rather than left running.

06What stops it

An agent that writes and mounts its own code needs limits that are not advice. These are the ones that refuse rather than warn.

LimitWhat it refuses
Permission modesA read-only agent cannot call a framework-mutating tool at all — the denial is tested through the executor, not by omitting the tool from a prompt.
BudgetsStep, token, and wall-clock ceilings stop a run rather than letting it spend. A stop is reported as a stop, never as a completed task.
Promotion containmentA component is promoted only from inside the session's staging root, checked after both paths are resolved — so .. and symlinks cannot spell a way out.
Plan modeHolds a run to reading and reasoning until a person approves what it intends to do.
SandboxingCommands run inside the session's sandbox, with the filesystem fenced by its mode.