Lesezeit: 6 Min.
Als wir Cloudflare Sandboxes im Juni letzten Jahres auf den Markt brachten, war die Prämisse einfach: KI-Agents müssen Code entwickeln und ausführen, und sie müssen dies an einem sicheren Ort tun.
Wenn sich ein Agent wie ein Entwickler verhält, bedeutet dies, Repositories zu klonen, Code in vielen Sprachen zu erstellen, Entwicklungsserver auszuführen usw. Um diese Aufgaben effektiv zu erledigen, benötigen er oft einen leistungsfähigen Computer (und wenn nicht, kann er zu etwas Leichtem greifen!).
Viele Entwickler kombinieren Lösungen mit Hilfe von VMs oder bestehenden Container-Lösungen, aber es gibt noch viele schwierige Probleme zu lösen:
Lastspitzen – Da jede Sitzung eine eigene Sandbox benötigt, müssen Sie oft viele Sandboxes schnell hochfahren, möchten jedoch nicht für ungenutzte Rechenleistung im Standby-Modus bezahlen.
Schnelle Wiederherstellung des Zustands – Jede Sitzung sollte schnell starten und schnell neu starten, um den vorherigen Zustand wiederherzustellen.
Sicherheit – Agents müssen sicher auf Dienste zugreifen, ihnen können aber keine Zugangsdaten anvertraut werden.
Steuerung – Es muss einfach sein, den Lebenszyklus der Sandbox programmatisch zu steuern, Befehle auszuführen, Dateien zu verwalten und mehr.
Ergonomie – Sie müssen sowohl Menschen als auch Agents eine einfache Schnittstelle zur Verfügung stellen, um die üblichen Vorgänge auszuführen.
Wir haben uns die Zeit genommen, diese Probleme zu lösen, damit Sie sich nicht darum kümmern müssen. Seit unserer ersten Einführung haben wir Sandboxes zu einem noch besseren Ort für die Ausführung von Agents in großem Umfang gemacht. Wir haben mit unseren ersten Partnern wie Figma zusammengearbeitet, die Agents in Containern mit Figma Make betreiben:
„Figma Make wurde entwickelt, um Entwicklern und Herstellern mit unterschiedlichem Hintergrund zu helfen, schneller von der Idee in die Produktion zu gelangen. Um dieses Ziel zu erreichen, benötigten wir eine Infrastrukturlösung, die zuverlässige, hoch skalierbare Sandboxes bereitstellen konnte, in denen wir nicht vertrauenswürdigen, von Agents und Nutzern erstellten Code ausführen konnten. Cloudflare Containers ist diese Lösung.“
– Alex Mullans, KI- und Entwicklerplattformen bei Figma
Wir möchten Sandboxes für noch mehr Unternehmen verfügbar machen. Deshalb freuen wir uns, heute anzukündigen, dass Sandboxes und Cloudflare Containers jetzt allgemein verfügbar sind.
Werfen wir einen Blick auf einige der jüngsten Änderungen an den Sandboxes:
Mit Secure Credential Injection können Sie authentifizierte Aufrufe tätigen, ohne dass der Agent jemals Zugriff auf Anmeldedaten hat
PTY-Unterstützung gibt Ihnen und Ihrem Agents ein echtes Terminal
Persistente Code-Interpreter geben Ihrem Agent einen Ort, an dem er zustandsbehaftete Python, JavaScript und TypeScript standardmäßig ausführen kann
Hintergrundprozesse und Live-Vorschau-URLs bieten eine einfache Möglichkeit, mit Entwicklungsservern zu interagieren und laufende Änderungen zu überprüfen
Die Überwachung durch das Dateisystem verbessert die Geschwindigkeit der Iteration, wenn Agents Änderungen vornehmen.
Snapshots ermöglichen es Ihnen, die Programmiersitzung eines Agents schnell wiederherzustellen
Höhere Obergrenzen und Active CPU Pricing erlauben es Ihnen, eine ganze Reihe von Agents in großem Maßstab einzusetzen, ohne für ungenutzte CPU-Zyklen zu zahlen
Bevor wir uns mit einigen der jüngsten Änderungen befassen, wollen wir kurz die Grundlagen betrachten.
Eine Cloudflare-Sandbox ist eine persistente, isolierte Umgebung, die von Cloudflare-Containern unterstützt wird. Sie fragen nach einem Namen für eine Sandbox. Wenn sie läuft, erhalten Sie sie. Wenn nicht, beginnt sie. Wenn sie untätig ist, versetzt sie sich automatisch in den Ruhezustand und wird aktiv, wenn sie eine Anfrage erhält. Mit Methoden wie exec, gitClone, writeFile und mehr ist es einfach, programmatisch mit der Sandbox zu interagieren.
import { getSandbox } from "@cloudflare/sandbox";
export { Sandbox } from "@cloudflare/sandbox";
export default {
async fetch(request: Request, env: Env) {
// Ask for a sandbox by name. It starts on demand.
const sandbox = getSandbox(env.Sandbox, "agent-session-47");
// Clone a repository into it.
await sandbox.gitCheckout("https://github.com/org/repo", {
targetDir: "/workspace",
depth: 1,
});
// Run the test suite. Stream output back in real time.
return sandbox.exec("npm", ["test"], { stream: true });
},
};
Solange Sie dieselbe ID angeben, können nachfolgende Anfragen von überall auf der Welt an dieselbe Sandbox gelangen.
Sichere Injektion von Anmeldedaten
Eines der größten Probleme bei Agents-Workloads ist die Authentifizierung. Für den Zugriff auf private Dienste benötigen Sie oft Agents, aber Sie können ihnen nicht vollständig mit unverschlüsselten Anmeldedaten vertrauen.
Sandboxes lösen dieses Problem, indem sie Anmeldeinformationen auf der Netzwerkebene über einen programmierbaren Egress-Proxy einspeisen. Das bedeutet, dass Sandbox-Agents niemals Zugriff auf die Anmeldedaten haben und Sie die Authentifizierungslogik vollständig nach Ihrem Ermessen anpassen können:
class OpenCodeInABox extends Sandbox {
static outboundByHost = {
"my-internal-vcs.dev": (request, env, ctx) => {
const headersWithAuth = new Headers(request.headers);
headersWithAuth.set("x-auth-token", env.SECRET);
return fetch(request, { headers: headersWithAuth });
}
}
}
Einen tieferen Einblick in diese Funktionsweise – einschließlich identitätsbasierter Injektion von Anmeldedaten, dynamischer Änderung von Regeln und Integration mit Workers-Bindungen – finden Sie in unserem aktuellen Blogbeitrag zur Sandbox-Authentifizierung.
Ein echtes Terminal, keine Simulation
Frühe Agentssysteme modellierten den Shell-Zugriff oft als eine Anfrage-Antwort-Schleife: einen Befehl ausführen, auf die Ausgabe warten, das Transkript wieder in die Prompts einfügen, wiederholen. Es funktioniert, entspricht aber nicht der tatsächlichen Arbeitsweise von Entwicklern in einem Terminal.
Menschen führen etwas aus, sehen zu, wie der Output gestreamt wird, unterbrechen ihn, stellen die Verbindung später wieder her und machen weiter. Auch die Agents profitieren von dieser Feedbackschleife.
Im Februar haben wir die PTY-Unterstützung eingeführt. Eine Pseudo-Terminal-Sitzung in einer Sandbox, die über WebSocket als Proxy geleitet wird und mit xterm.js kompatibel ist.
Rufen Sie einfach sandbox.terminal auf, um das Backend bereitzustellen:
// Worker: upgrade a WebSocket connection into a live terminal session
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url);
if (url.pathname === "/terminal") {
const sandbox = getSandbox(env.Sandbox, "my-session");
return sandbox.terminal(request, { cols: 80, rows: 24 });
}
return new Response("Not found", { status: 404 });
},
};
Und verwenden Sie xterm addon, um es vom Client aus aufzurufen:
// Browser: connect xterm.js to the sandbox shell
import { Terminal } from "xterm";
import { SandboxAddon } from "@cloudflare/sandbox/xterm";
const term = new Terminal();
const addon = new SandboxAddon({
getWebSocketUrl: ({ origin }) => `${origin}/terminal`,
});
term.loadAddon(addon);
term.open(document.getElementById("terminal-container")!);
addon.connect({ sandboxId: "my-session" });
Dadurch können Agents und Entwickler eine vollständige PTY nutzen, um diese Sitzungen live zu debuggen.
Jede Terminalsitzung erhält ihre eigene isolierte Shell, ihr eigenes Arbeitsverzeichnis, ihre eigene Umgebung. Öffnen Sie so viele, wie Sie benötigen, genau wie auf Ihrem eigenen Rechner. Die Ausgabe wird serverseitig gepuffert, sodass bei der Wiederherstellung der Verbindung das wiederholt wird, was Sie verpasst haben.
Ein Code-Interpreter mit Gedächtnis
Für Datenanalyse, Skripterstellung und explorative Workflows bieten wir auch eine Abstraktion auf höherer Ebene: einen persistenten Codeausführungskontext.
Das Schlüsselwort lautet „persistent“. Viele Code-Interpreter-Implementierungen führen jedes Snippet isoliert aus, sodass der Zustand zwischen den Aufrufen verschwindet. Sie können eine Variable nicht in einem Schritt setzen und im nächsten lesen.
Sandboxes ermöglichen es Ihnen, „Kontexte“ zu erstellen, die den Zustand beibehalten. Variablen und Importe bleiben über Aufrufe hinweg genauso bestehen wie in einem Jupyter Notebook:
// Create a Python context. State persists for its lifetime.
const ctx = await sandbox.createCodeContext({ language: "python" });
// First execution: load data
await sandbox.runCode(`
import pandas as pd
df = pd.read_csv('/workspace/sales.csv')
df['margin'] = (df['revenue'] - df['cost']) / df['revenue']
`, { context: ctx });
// Second execution: df is still there
const result = await sandbox.runCode(`
df.groupby('region')['margin'].mean().sort_values(ascending=False)
`, { context: ctx, onStdout: (line) => console.log(line.text) });
// result contains matplotlib charts, structured json output, and Pandas tables in HTML
Server starten. URL abrufen. Ausliefern.
Agents sind nützlicher, wenn sie etwas erstellen und es dem Nutzer sofort zeigen können. Sandboxes unterstützen Hintergrundprozesse, Bereitschaftsprüfungen und Vorschau-URLs. Damit kann ein Agent einen Entwicklungsserver starten und einen Live-Link teilen, ohne die Konversation zu verlassen.
// Start a dev server as a background process
const server = await sandbox.startProcess("npm run dev", {
cwd: "/workspace",
});
// Wait until the server is actually ready — don't just sleep and hope
await server.waitForLog(/Local:.*localhost:(\d+)/);
// Expose the running service with a public URL
const { url } = await sandbox.exposePort(3000);
// url is a live public URL the agent can share with the user
console.log(`Preview: ${url}`);
Mit waitForPort() und waitForLog() können Agents ihre Arbeit auf der Grundlage echter Signale des laufenden Programms statt mit Rateversuchen sequenzieren. Das ist deutlich eleganter als die übliche Alternative – meist irgendeine Variante von sleep(2000), gefolgt von blindem Vertrauen.
Moderne Entwicklungsabläufe sind ereignisgesteuert: Datei speichern, Build erneut ausführen. Konfiguration ändern, Server neu starten. Test anpassen, Suite erneut ausführen.
Wir haben sandbox.watch() im März veröffentlicht. Sie gibt einen SSE-Stream zurück, der von nativem inotify unterstützt wird, dem Kernel-Mechanismus, den Linux für Dateisystemereignisse verwendet.
import { parseSSEStream, type FileWatchSSEEvent } from '@cloudflare/sandbox';
const stream = await sandbox.watch('/workspace/src', {
recursive: true,
include: ['*.ts', '*.tsx']
});
for await (const event of parseSSEStream<FileWatchSSEEvent>(stream)) {
if (event.type === 'modify' && event.path.endsWith('.ts')) {
await sandbox.exec('npx tsc --noEmit', { cwd: '/workspace' });
}
}
Dies ist eine dieser Primitiven, die unauffällig das ändern, was Agents tun können. Ein Agent, der das Dateisystem in Echtzeit beobachten kann, kann an denselben Feedbackschleifen teilnehmen wie ein menschlicher Entwickler.
Schnelles Aufwachen mit Snapshots
Stellen Sie sich einen (menschlichen) Entwickler vor, der an seinem Laptop arbeitet. Er klont ein Repo, führt npm install aus, schreibt Code, pusht einen PR und schließt dann seinen Laptop, während er auf das Code-Review warten. Wenn es an der Zeit ist, die Arbeit wieder aufzunehmen, öffnen er einfach den Laptop wieder und macht dort weiter, wo er aufgehört haben.
Wenn ein Agent diesen Arbeitsablauf auf einer einfachen Containerplattform replizieren möchte, stoßen Sie auf ein Problem. Wie können Sie dort schnell weitermachen, wo Sie aufgehört haben? Sie könnten eine Sandbox am Laufen halten, zahlen Sie dann aber für ungenutzte Rechenleistung. Sie könnten neu mit dem Container-Image beginnen, müssen dann aber auf eine lange Git-Clone und npm-Installation warten.
Unsere Antwort sind Snapshots, die in den kommenden Wochen eingeführt werden.
Ein Snapshot speichert den vollständigen Festplattenstatus eines Containers, die Betriebssystemkonfiguration, installierte Abhängigkeiten, geänderte Dateien, Datendateien und mehr. Dann können Sie alles später schnell wiederherstellen.
Sie können eine Sandbox so konfigurieren, dass beim Wechsel in den Ruhezustand automatisch eine Momentaufnahme erstellt wird.
class AgentDevEnvironment extends Sandbox {
sleepAfter = "5m";
persistAcrossSessions = {type: "disk"}; // you can also specify individual directories
}
Sie können auch programmgesteuert einen Snapshot erstellen und manuell wiederherstellen. Dies ist nützlich für die Checkpoint-Arbeit oder das Forken von Sitzungen. Wenn Sie beispielsweise vier Instanzen eines Agents parallel ausführen wollten, können Sie problemlos vier Sandboxes aus demselben Zustand starten.
class AgentDevEnvironment extends Sandbox {}
async forkDevEnvironment(baseId, numberOfForks) {
const baseInstance = await getSandbox(baseId);
const snapshotId = await baseInstance.snapshot();
const forks = Array.from({ length: numberOfForks }, async (_, i) => {
const newInstance = await getSandbox(`${baseId}-fork-${i}`);
return newInstance.start({ snapshot: snapshotId });
});
await Promise.all(forks);
}
Snapshots werden in R2 innerhalb Ihres Kontos gespeichert, was Ihnen Dauerhaftigkeit und Standortunabhängigkeit bietet. Das Tiered Caching-System von R2 ermöglicht eine schnelle Wiederherstellung in der gesamten Region: auf der Erde.
In zukünftigen Versionen wird auch der Live-Speicherstatus erfasst, so dass laufende Prozesse genau an der Stelle fortgesetzt werden können, an der sie unterbrochen wurden. Ein Terminal und ein Editor werden genau in dem Zustand wieder geöffnet, in dem sie sich beim letzten Schließen befanden.
Wenn Sie den Sitzungsstatus wiederherstellen möchten, bevor die Snapshots live gehen, können Sie noch heute die Sicherungs- und Wiederherstellungsmethoden verwenden. Diese speichern ebenfalls Verzeichnisse mit R2 und stellen sie wieder her, sind aber nicht so leistungsfähig wie echte Snapshots auf VM-Ebene. Sie können dennoch erhebliche Geschwindigkeitsvorteile gegenüber dem einfachen Neuerstellen des Sitzungszustands bringen.
Das Booten einer Sandbox, das Klonen von „axios“ und die Installation von npm dauert 30 Sekunden. Die Wiederherstellung aus einem Backup dauert zwei Sekunden.
Bleiben Sie dran – die offizielle Snapshot-Version kommt bald.
Höhere Obergrenzen und aktive CPU-Preisgestaltung
Seit unserem ersten Start haben wir die Kapazität stetig erhöht. Nutzer unseres Standardplans können jetzt 15.000 gleichzeitige Instanzen des „Lite“-Instanztyps, 6.000 Instanzen des Basic-Modells und über 1.000 gleichzeitige größere Instanzen ausführen. Wenden Sie sich gerne an uns, um noch mehr Instanzen auszuführen!
Außerdem haben wir unser Preismodell angepasst, um den Einsatz in großem Maßstab kosteneffizienter zu gestalten. Sandboxes berechnen jetzt nur noch die aktiv genutzten CPU-Zyklen. Das bedeutet, dass Sie nicht für ungenutzte CPU-Zyklen zahlen, während Ihr Agent auf die Antwort eines LLMs wartet.
So sieht ein Computer aus
Vor neun Monaten haben wir eine Sandbox veröffentlicht, die Befehle ausführen und auf ein Dateisystem zugreifen kann. Das reichte aus, um das Konzept zu beweisen.
Was wir jetzt haben, ist grundlegend anders. Eine Sandbox ist heute eine vollständige Entwicklungsumgebung: ein Terminal, mit dem Sie einen Browser verbinden können, ein Code-Interpreter mit persistentem Zustand, Hintergrundprozesse mit Live-Vorschau-URLs, ein Dateisystem, das Änderungsereignisse in Echtzeit ausgibt, Egress-Proxys für eine sichere Credential Injection und ein Snapshot-Mechanismus, der Warmstarts nahezu sofort ermöglicht.
Darauf aufbauend ergibt sich ein überzeugendes Muster: Agents, die echte Entwicklungsarbeit leisten. Ein Repo klonen, installieren, die Tests ausführen, die Fehler lesen, den Code bearbeiten, die Tests erneut ausführen. Die Art von enger Feedbackschleife, die menschliche Entwickler effektiv macht – jetzt steht sie auch dem Agenten zur Verfügung.
Wir sind bei Version 0.8.9 des SDK. Legen Sie noch heute los:
npm i @cloudflare/sandbox@latest