Agent Experience / Cloudflare

molt.

an agent breaks its own code and fixes it, live, in a fresh container.

Read how it works
AX–MOLT–01
self-healing / ephemeral compute

Overview

An agent wrote a tool, the loop broke it, and the agent fixed it.

That run happened in a Cloudflare Container that was created when you pressed Watch and destroyed when the loop ended. The agent edited real files; a separate verifier ran the tool and decided whether it passed. The agent’s own report did not decide the verdict.

The repository contains the loop source. Read it, run it, and copy the checks you need into your own agent.

The pattern

Let a verifier decide done, not the agent.

An agent that grades its own work reports success on code that does not run. molt sends the verdict through a verifier the agent does not control. It does three things.

1 · Independent acceptance

A verifier separate from the agent runs the tool on fixed inputs and returns pass or fail. The agent cannot mark its own work done.

2 · Bounded heal

When a check fails, the exact failing case goes back to the agent as the next prompt. Attempts are capped, so a model that cannot find the bug stops instead of looping.

3 · Scope confinement

The agent may write only inside one directory. An earlier run rewrote a harness file and broke the build; the scope check now refuses writes outside the generated-tools folder.

How it works

build, fault, detect, heal, accept

The acceptance check runs the live tool on fixed inputs and passes only when every case is exact. It returns the verdict shown as HEALED or FAILED.

independent verifiersrc/loop/scenario.ts
async accept(ctx) {
  const present = ctx.tools.some((tool) => tool.name === "wordcount");
  if (!present) return { ok: false, detail: "wordcount not present in live registry" };
  const cases = [
    { text: "the quick brown fox", expected: 4 },
    { text: "hello", expected: 1 },
    { text: "   ", expected: 0 },
    { text: "one  two   three", expected: 3 },
  ];
  for (const testCase of cases) {
    const raw = await ctx.callTool("wordcount", { text: testCase.text });
    const got = Number(String(raw).trim().match(/-?\d+/)?.[0] ?? "NaN");
    if (got !== testCase.expected) {
      return { ok: false, detail: `wordcount(...) = ${got}, expected ${testCase.expected}` };
    }
  }
  return { ok: true, detail: `wordcount passed ${cases.length} fixture cases` };
}

When the verifier fails, molt feeds the precise failure back and tries again, up to a cap:

bounded heal loopsrc/loop/index.ts
let accepted = broken; // currently failing
while (attempts < MAX_HEAL_ATTEMPTS && !accepted.ok) {
  attempts += 1;
  const prompt = attempts === 1
    ? scenario.healPrompt
    : `Still wrong: ${accepted.detail}. Re-read and fix it exactly.`;
  await boundedPrompt(agent, prompt, forward, emit);
  await reloadGenerated(registry, agent, config.root, scenario.generatedFile);
  accepted = await scenario.accept(makeAcceptCtx(registry)); // independent
}

Cloudflare primitives

What runs it

The Worker creates one Container for the run and destroys it after the verdict.

Compute

Container

Holds the temporary working tree. The agent edits files here. The instance is destroyed after the verdict.

State

Durable Object

Owns the session and bridges the browser WebSocket to the container.

Model

Workers AI

Runs Kimi K2.7 Code. The API credential is passed to the Container and is not sent to the browser.

Edge

Worker

Serves this page and routes /ws/loop to the container, origin-checked.

Copy it

Use the same three checks

The three checks do not depend on molt. Copy them into your own agent loop.

// 1. An independent verifier owns "done".
const verdict = await accept(liveTool);          // runs real checks
if (verdict.ok) finish(verdict);

// 2. On failure, feed back the exact reason — bounded.
else if (attempts < MAX) retry(`Still wrong: ${verdict.detail}`);

// 3. Confine what the agent can touch.
assertWritablePath(root, target); // refuses writes outside the allowed dir

molt records its own receipt for each run; map those fields onto whatever your system already logs.

Run it

Run the loop locally

The command runs the loop on your machine and writes a receipt for the run. The repository holds the full source.

bun install && bun run loop