effidevFlutter · Cloudflare-Edge · Cloud-Kostenoptimierung
Deutsch

Cloudflare Agents SDK: Zustandsbehaftete KI-Agenten am Edge

Zustandsbehaftete KI-Agenten mit Cloudflare Agents SDK erstellen

Das Aufrufen eines LLM über eine API zur Antwortgenerierung beherrscht heute jeder. Die eigentliche Herausforderung liegt im nächsten Schritt: Ein Agent, der sich an frühere Gespräche erinnert, externe Tools aufruft, auf menschliche Genehmigungen wartet, bevor er fortfährt, und Aufgaben selbstständig nach einem Cron-Zeitplan startet — kurz gesagt, ein „zustandsbehafteter (stateful) Produktions-Agent“. Um einen solchen aufzubauen, müssen Zustandsverwaltung, persistenter Speicher, Echtzeitkommunikation und langlebige Workflows manuell orchestriert werden. Wer Redis + PostgreSQL + WebSocket-Server + Queues + Cron-Jobs separat betreibt, schafft eine Infrastruktur, die komplexer ist als der Agent selbst.

Das von Cloudflare auf der Agents Week 2026 vorgestellte Agents SDK löst dieses Problem auf einer einzigen Schicht: Durable Objects. Eine Agenten-Instanz entspricht genau einem Durable Object, das seinen Zustand in einer integrierten SQLite-Datenbank persistiert, über WebSockets in Echtzeit mit dem Frontend kommuniziert und autonome Ausführungen über Alarme und Cron-Jobs abwickelt. Ohne zusätzliche Infrastruktur genügt ein einziger Befehl wrangler deploy, um den Agenten auf mehr als 300 PoPs weltweit bereitzustellen.

Dieser Artikel deckt alles ab — von der Architektur des Agents SDK über die Implementierung der Agent-Klasse, typsichere RPCs mit dem @callable()-Dekorator, die Integration von React-Hooks (useAgent/useAgentChat) und Human-in-the-Loop-Genehmigungsmustern bis hin zu Produktionslimits und Kosten — auf einem Niveau, das direkt in der Praxis eingesetzt werden kann.

Kernpunkte

  • Die Agenten des Agents SDK laufen auf Durable Objects und bieten pro Instanz bis zu 1 GB integriertes SQLite, 30 Sekunden CPU-Zeit (pro Anfrage zurückgesetzt) sowie unbegrenzte Wartezeit nach Echtzeit (Wall-Clock).
  • Durch Erben der Agent-Klasse und Bereitstellen von Methoden über den @callable()-Dekorator kann das Frontend über den useAgent-Hook sofort WebSocket-basierte, typsichere RPCs aufrufen.
  • Human-in-the-Loop unterstützt das Gating von Tool-Aufrufen über das needsApproval-Flag sowie Wartezeiten von Tagen bis Monaten mittels waitForApproval() in Cloudflare Workflows.
  • Agenten können Aufgaben über Cron-Zeitpläne und Alarme autonom starten, ohne auf ein reines Anfrage-Antwort-Muster beschränkt zu sein.
  • Die Abrechnung erfolgt nach den Durable-Objects-Preisen des Workers Paid Plans, wobei mehrere zehn Millionen gleichzeitige Agenten-Instanzen pro Konto betrieben werden können.

Agents SDK-Architektur: Warum Durable Objects?

Bisherige serverlose KI-Agenten-Implementierungen setzen meist auf die Kombination „zustandslose Funktion + externer Speicher“. Lambda oder Cloud Functions rufen das LLM auf, der Gesprächsverlauf liegt in Redis oder DynamoDB, langlebige Zustände in Step Functions und die Echtzeitkommunikation übernimmt ein separater WebSocket-Server. Für einen einzigen Agenten müssen 4 bis 5 Dienste kombiniert werden, und der Glue-Code zur Gewährleistung der Konsistenz zwischen den Diensten wird länger als die eigentliche Agentenlogik.

Das Agents SDK komprimiert diese Kombination auf ein einziges Durable Object. Laut der offiziellen Architektur-Dokumentation von Cloudflare sieht die Struktur einer Agenten-Instanz wie folgt aus:

Rolle Was Durable Objects bieten Entsprechender Dienst in traditioneller Architektur
Compute Single-Thread-Isolate, 30 s CPU-Zeit pro Anfrage Lambda / Cloud Run
Persistenter Zustand Integrierte SQLite-Datenbank (bis zu 1 GB pro Instanz) DynamoDB / Redis
Echtzeitkommunikation Natives WebSocket (mit Hibernation-Unterstützung) Pusher / Socket.IO-Server
Scheduling Alarm-API + Cron-Ausdrücke CloudWatch Events / Cron-Server
Globales Routing Global eindeutige ID für Zugriff auf dieselbe Instanz von überall Route 53 + Load Balancer
Fehlertoleranz Automatische Migration, Neustart auf anderem PoP bei Ausfall Eigene Implementierung

Der entscheidende Punkt ist das 1:1-Mapping: „Agenten-Instanz = Durable Object-Instanz“. Ruft der Agent this.setState() auf, wird dies sofort in die integrierte SQLite-Datenbank geschrieben und automatisch an alle verbundenen WebSocket-Clients übertragen. Selbst während der Agent auf eine LLM-Antwort wartet, kann das Durable Object nach Echtzeit (Wall-Clock) unbegrenzt warten (ohne CPU-Zeit zu verbrauchen). Dadurch lassen sich langlebige Workflows direkt im Agenten abwickeln — ganz ohne externe Warteschlangen oder Step Functions.

Der praktische Vorteil dieser Architektur liegt im Verschwinden der Bereitstellungskomplexität. Ein einziger Befehl wrangler deploy lädt den Agentencode, den Zustandsspeicher, die WebSocket-Endpunkte und den Scheduler auf einmal in das globale Netzwerk von Cloudflare hoch. Es ist keine separate Datenbankbereitstellung, kein Skalieren von WebSocket-Servern und keine Einrichtung von Cron-Jobs erforderlich.

Implementierung der Agent-Klasse: Zustandsverwaltung und @callable RPC

Das Grundgerüst eines Agenten beginnt mit dem Erben der Agent-Klasse. Erstellen wir ein Projekt basierend auf dem agents-starter Template auf GitHub und betrachten wir die Kernstruktur.

# 프로젝트 생성 (2026-08 기준 최신 템플릿)
npm create cloudflare@latest -- --template cloudflare/agents-starter my-agent
cd my-agent

Nachfolgend ist ein Beispiel für die serverseitige Implementierung eines Support-Ticket-Agenten dargestellt. Dieser Code demonstriert das Muster zur Abwicklung von Zustandspersistenz + typsicherem RPC + Tool-Aufrufen innerhalb einer einzigen Klasse.

// src/server.ts
import { Agent, callable } from "agents";
import { AIChatAgent } from "@cloudflare/ai-chat";

// 에이전트 상태 타입 정의
export interface TicketState {
  ticketId: string | null;
  status: "idle" | "investigating" | "waiting-approval" | "resolved";
  history: Array<{ role: string; content: string; timestamp: number }>;
  metadata: Record<string, string>;
}

export class SupportAgent extends AIChatAgent<Env, TicketState> {
  // 초기 상태 — Durable Object 생성 시 SQLite에 자동 저장
  initialState: TicketState = {
    ticketId: null,
    status: "idle",
    history: [],
    metadata: {},
  };

  // @callable()로 노출한 메서드는 프론트엔드에서 agent.stub.assignTicket() 으로 호출 가능
  @callable()
  async assignTicket(ticketId: string, priority: string): Promise<string> {
    // setState()는 SQLite에 즉시 기록 + 연결된 모든 클라이언트에 브로드캐스트
    this.setState({
      ...this.state,
      ticketId,
      status: "investigating",
      metadata: { ...this.state.metadata, priority },
    });

    // Workers AI로 티켓 분석 (에지에서 추론)
    const analysis = await this.env.AI.run("@cf/meta/llama-3.3-70b-instruct-fp8-fast", {
      messages: [
        { role: "system", content: "고객 지원 티켓을 분석하고 해결 방안을 제시하라." },
        { role: "user", content: `티켓 ${ticketId}, 우선순위: ${priority}` },
      ],
    });

    return analysis.response ?? "분석 완료";
  }

  @callable()
  async getStatus(): Promise<TicketState> {
    return this.state;
  }

  // 크론 스케줄: 매 시간 미해결 티켓 체크
  async onCronTrigger(cron: string): Promise<void> {
    if (this.state.status === "investigating") {
      const elapsed = Date.now() - (this.state.history.at(-1)?.timestamp ?? 0);
      if (elapsed > 3600_000) {
        // 1시간 이상 미해결 → 에스컬레이션 알림
        await this.escalate();
      }
    }
  }

  private async escalate(): Promise<void> {
    this.setState({ ...this.state, metadata: { ...this.state.metadata, escalated: "true" } });
    // 슬랙 웹훅, 이메일 등 알림 전송 로직
  }
}

Wichtiger Hinweis: Der @callable()-Dekorator ist exklusiv für WebSocket-basierte RPCs gedacht. Beim Aufruf von Agenten-Methoden innerhalb desselben Workers oder aus einem anderen Durable Object sollte das Standard-Durable-Object-RPC (this.env.AGENT.get(id)) verwendet werden. Die Verwendung von @callable() für interne Aufrufe erzeugt unnötigen WebSocket-Overhead.

Auch die Einbindung des Agenten als Durable Object in der Konfigurationsdatei wrangler.jsonc darf nicht vergessen werden:

// wrangler.jsonc
{
  "name": "support-agent",
  "main": "src/index.ts",
  "compatibility_date": "2026-07-28",
  "durable_objects": {
    "bindings": [
      {
        "name": "SUPPORT_AGENT",
        "class_name": "SupportAgent"
      }
    ]
  },
  "migrations": [
    { "tag": "v1", "new_sqlite_classes": ["SupportAgent"] }
  ],
  "ai": { "binding": "AI" }
}

React-Frontend-Integration: Die Hooks useAgent und useAgentChat

Das Agents SDK bietet spezielle React-Hooks, um die Verbindung zwischen Frontend und Agent deklarativ abzuwickeln. Laut dem offiziellen React-Integrationsleitfaden unterscheiden sich die Aufgaben der drei verfügbaren Hooks deutlich:

Hook Paket Verwendungszweck
useAgent agents/react Generische Agentenverbindung. Zustandssynchronisierung + RPC-Aufrufe
useAgentChat @cloudflare/ai-chat/react Spezifisch für Chats. Nachrichtenspeicherung, Streaming, automatische Tool-Ausführung
useVoiceAgent @cloudflare/voice Sprach-STT/TTS. Echtzeit-Sprachverarbeitung über denselben WebSocket

Nachfolgend sehen Sie ein Beispiel für eine React-Komponente, die sich über useAgent mit dem zuvor erstellten SupportAgent verbindet. Dieser Code demonstriert das Muster zur deklarativen Verwaltung der WebSocket-Verbindungssteuerung + automatischen Zustandssynchronisierung + typsicheren RPC-Aufrufen.

// src/client.tsx
import { useAgent } from "agents/react";
import { useState, useCallback } from "react";
import type { SupportAgent, TicketState } from "./server";

function SupportDashboard() {
  const [ticket, setTicket] = useState<TicketState | null>(null);
  const [ticketId, setTicketId] = useState("");

  // useAgent는 WebSocket 연결을 자동으로 관리하고,
  // 에이전트의 setState() 호출 시 onStateUpdate가 자동으로 트리거된다
  const agent = useAgent<SupportAgent, TicketState>({
    agent: "SupportAgent",
    onStateUpdate: (state) => setTicket(state),
    onError: (error) => console.error("Agent connection error:", error),
  });

  const handleAssign = useCallback(async () => {
    if (!agent.stub || !ticketId) return;
    // 타입 안전한 RPC 호출 — @callable() 메서드만 stub에 노출됨
    const result = await agent.stub.assignTicket(ticketId, "high");
    console.log("분석 결과:", result);
  }, [agent.stub, ticketId]);

  return (
    <div>
      <input
        value={ticketId}
        onChange={(e) => setTicketId(e.target.value)}
        placeholder="티켓 ID 입력"
      />
      <button onClick={handleAssign} disabled={!agent.connected}>
        티켓 할당
      </button>
      {ticket && (
        <div>
          <p>상태: {ticket.status}</p>
          <p>우선순위: {ticket.metadata.priority ?? "미지정"}</p>
        </div>
      )}
    </div>
  );
}

useAgentChat ist ein noch spezialisierterer Hook, der die Speicherung des Nachrichtenverlaufs in SQLite, die Verarbeitung von LLM-Streaming-Antworten und das automatische Inlining von Tool-Aufrufergebnissen intern übernimmt. Beim Erstellen von Chat-UIs reduziert die Verwendung von useAgentChat anstelle von useAgent die Code-Menge um mehr als die Hälfte.

Human-in-the-Loop: Tool-Genehmigungs-Gating und Langzeit-Warte-Muster

Eine der anspruchsvollsten Aufgaben bei Produktions-KI-Agenten besteht darin, „sicherzustellen, dass der Agent vor der Ausführung kritischer Aktionen eine menschliche Bestätigung einholt“. Das Agents SDK unterstützt dies auf drei Ebenen.

Muster 1: Tool-Gating mit needsApproval. Wird bei der Tool-Definition needsApproval: true gesetzt, stoppt der Agent die Ausführung, sobald er versucht, das entsprechende Tool aufzurufen, und wechselt in den Zustand approval-requested. Sobald vom Frontend eine Genehmigung oder Ablehnung gesendet wird, setzt der Agent die Ausführung fort oder bricht sie ab.

// 도구 정의 예시 — 결제 처리 도구에 승인 게이트 적용
const tools = [
  {
    name: "process_refund",
    description: "고객에게 환불을 처리한다",
    parameters: {
      type: "object",
      properties: {
        amount: { type: "number", description: "환불 금액 (USD)" },
        reason: { type: "string", description: "환불 사유" },
      },
      required: ["amount", "reason"],
    },
    // 이 플래그가 핵심 — 에이전트가 이 도구를 호출하려 하면 일시 정지
    needsApproval: true,
  },
];

Wichtiger Hinweis: needsApproval eignet sich für Echtzeit-Genehmigungen innerhalb einer Sitzung. Schließt der Benutzer den Browser, wird die WebSocket-Verbindung getrennt. Daher eignet sich dieses Muster nicht für Szenarien, in denen der Genehmigungsprozess mehere Stunden oder länger dauern kann.

Muster 2: waitForApproval() in Cloudflare Workflows. Wenn lange Wartezeiten erforderlich sind (z. B. Workflows, bei denen die Genehmigung durch einen Administrator erst am nächsten Tag erfolgt), wird die Methode waitForApproval() von Cloudflare Workflows verwendet. Diese Methode erstellt ein dauerhaftes Gate auf dem Durable Object. Selbst wenn die Agenten-Instanz aus dem Speicher entfernt wird (Hibernation), wacht sie bei Eingang des Genehmigungsevents automatisch wieder auf und setzt den Workflow fort. Wartezeiten von Tagen bis Monaten sind so problemlos möglich.

Muster 3: MCP-Elicitation. Wenn der Agent mit einem Model Context Protocol (MCP)-Server kommuniziert und auf Seiten des MCP-Servers zusätzliche Informationen benötigt werden, können über configureElicitationHandlers() Rückfragen direkt an den Benutzer gestellt werden. Dies ist besonders nützlich, wenn der Agent als MCP-Client mehrere externe Tools orchestriert.

Scheduling und autonome Ausführung: Cron, Alarme und Webhooks

Traditionelle KI-Chatbots reagieren nur, wenn der Benutzer eine Nachricht sendet. Produktions-Agenten müssen jedoch in der Lage sein, Aufgaben selbstständig zu starten. Agenten im Agents SDK erben die Alarm-API von Durable Objects und unterstützen vier autonome Ausführungsmuster:

Trigger Einrichtungsmethode Geeignetes Szenario
Cron-Zeitplan triggers.crons in wrangler.jsonc Regelmäßige Aufgaben (stündlich/täglich), z. B. Berichte, Monitoring
Alarm this.ctx.storage.setAlarm(timestamp) Einmalige Ausführung zu einem bestimmten Zeitpunkt (terminierter Versand, Erinnerungen)
Webhook-Empfang Routing zum Agenten im fetch-Handler des Workers Reaktion auf externe Events (Stripe-Zahlungsabschluss, GitHub PR-Merge)
E-Mail-Empfang email()-Handler E-Mail-basierte automatische Antwort und Klassifizierung

Der Hauptvorteil dieser Struktur liegt darin, dass im Leerlauf des Agenten keine Kosten entstehen. Dank der Hibernation-API von Durable Objects kann die Agenten-Instanz aus dem Speicher entfernt werden, während die WebSocket-Verbindung bestehen bleibt. Wenn ein Alarm oder Cron-Job ausgelöst wird, wacht der Agent automatisch auf, führt die Aufgabe aus und wechselt anschließend wieder in den Ruhezustand. Da keine dauerhaft laufenden VM-Instanzen erforderlich sind, werden selbst bei der zeitgleichen Bereitstellung von Tausenden Agenten nur die tatsächlich aktiven Agenten abgerechnet.

// Cron-Trigger-Konfiguration (wrangler.jsonc)
{
  "triggers": {
    "crons": ["0 */6 * * *"]  // Ausführung alle 6 Stunden
  }
}

Produktions-Deployment: Limits, Kosten und Betriebs-Checkliste

Beim Deployment des Agents SDK in der Produktion müssen die folgenden Limits und Kostenstrukturen beachtet werden. Dies sind die Werte von der Cloudflare Workers Preis-Seite und der Durable Objects Preis-Seite (Stand August 2026).

Kategorie Wert Anmerkung
Gleichzeitige Agenten-Instanzen pro Konto Mehrere zehn Millionen Hard Limit kann auf Anfrage erhöht werden
Max. Zustandsgröße pro Instanz 1 GB (SQLite) Key-Value-Speicher ebenfalls separat nutzbar
CPU-Zeit pro Anfrage 30 s Wird pro HTTP-Anfrage oder WebSocket-Nachricht zurückgesetzt
Wartezeit nach Wall-Clock Unbegrenzt Warten auf LLM-Antworten verbraucht keine CPU-Zeit
Anzahl Agenten-Definitionen ~250.000 Gesamtes Konto
Durable Objects Preis (Paid) $0,15 pro 1 Mio. Anfragen + $12,50 pro GB-s/Monat Bei Hibernation wird die Wall-Clock-Zeit nicht berechnet
Workers AI Inferenz Variiert je nach Modell Llama 3.3 70B: $0,27 pro 1 Mio. Input-Token

Drei wichtige Punkte für den Betrieb:

  1. Zustand bereinigen, um das SQLite-Limit von 1 GB nicht zu überschreiten. Wenn sich der Gesprächsverlauf unbegrenzt ansammelt, wird das Limit erreicht. Es ist eine Strategie erforderlich, ältere Verläufe in R2 zu archivieren und in SQLite nur die letzten N Einträge zu behalten.

  2. Das CPU-Limit von 30 Sekunden beachten. Der LLM-Aufruf selbst ist ein await-Warteprozess und verbraucht keine CPU-Zeit. Wenn jedoch die Logik zum Parsen und Nachbearbeiten der Antwort komplex ist, kann das CPU-Limit von 30 Sekunden überschritten werden. Aufwendige Nachbearbeitungen sollten in separate Worker ausgelagert oder asynchron über Cloudflare Queues verarbeitet werden.

  3. Hibernation aktiv nutzen. Selbst bei bestehender WebSocket-Verbindung sorgt die Verwendung von hibernateWebSocket() dafür, dass der Agent aus dem Speicher entfernt wird, solange keine Nachrichten fließen. Dadurch fällt die GB-s-Abrechnung nur für die aktive Verarbeitungszeit an, was die Kosten drastisch reduziert. Im Leitfaden WebSocket Hibernation wird das Einsparpotenzial dieses Musters im Detail beschrieben.

Vergleich mit bestehenden Agenten-Frameworks: LangGraph und Mastra

Das Agents SDK ist nicht die einzige Option. Ein Vergleich mit anderen in dieser Kategorie weit verbreiteten Agenten-Frameworks macht die Positionierung des Agents SDK deutlich.

Vergleichskriterium Cloudflare Agents SDK LangGraph Mastra
Ausführungsumgebung Cloudflare Edge (exklusiv) Überall (Cloud, lokal) Überall (Node.js)
Zustandsverwaltung Durable Objects integriertes SQLite Externe Checkpointer (Redis, Postgres) Externe Datenbank erforderlich
Echtzeitkommunikation Natives WebSocket + React-Hooks Manuell oder via LangServe Manuell
Langlebige Ausführung Hibernation + Workflows AsyncIO + externe Queue Externe Queue erforderlich
Deployment wrangler deploy Ein-Befehl Container/Serverless manuelle Einrichtung Container/Serverless manuelle Einrichtung
Vendor Lock-in Hoch (exklusiv für Cloudflare) Niedrig Niedrig
Stärken Zero-Infrastruktur, Global Edge, Kosteneffizienz Graphbasierte komplexe Workflows, Flexibilität Schlanke API, schnelles Prototyping

Der wesentliche Trade-off des Agents SDK besteht darin, dass „die Infrastrukturkomplexität auf null reduziert wird, man sich jedoch vollständig an Cloudflare bindet“. Für Teams, die bereits Cloudflare Workers als Hauptplattform nutzen, bietet das Agents SDK den schnellsten Weg zur Produktion. Wenn jedoch eine Multi-Cloud-Strategie zwingend erforderlich ist oder die Zustandsgraphik des Agenten komplexe DAG-/zyklische Strukturen erfordert, ist LangGraph besser geeignet.

Häufig gestellte Fragen

Was unterscheidet das Agents SDK von Workers AI?

Workers AI ist eine Modell-Inferenz-API. Es ist eine Engine zur Ausführung von Modellen wie Llama oder Whisper am Edge. Das Agents SDK ist ein Agenten-Framework und stellt die Infrastruktur bereit, aus der das „Gehirn“ des Agenten besteht — einschließlich Zustandsverwaltung, Tool-Aufrufen, Benutzerinteraktions-Handling und Scheduling. Normalerweise werden beide zusammen eingesetzt, indem innerhalb des Agents SDK Workers AI als Inferenz-Backend aufgerufen wird.

Können mehere Benutzer mit einem einzigen Agenten verbunden werden?

Ja, das ist möglich. Ein Durable Object kann mehrere WebSocket-Verbindungen gleichzeitig aufnehmen. Wenn Sie die Agenten-ID wie eine Chatroom-ID verwenden, können sich mehrere Benutzer mit demselben Agenten verbinden und Zustände in Echtzeit teilen. Aufgrund der Single-Threaded-Natur von Durable Objects gibt es jedoch Leistungsgrenzen bei Szenarien mit extrem hohen gleichzeitigen Schreibzugriffen (Tausende pro Sekunde).

Kann das Agents SDK zu einem bestehenden Workers-Projekt hinzugefügt werden?

Ja, das ist möglich. Installieren Sie das Paket agents, fügen Sie die Durable-Objects-Bindings in wrangler.jsonc hinzu und rufen Sie routeAgentRequest(request, env) im fetch-Handler des Workers auf. Dadurch koexistiert das bestehende Routing mit dem Agenten-Routing. Sie können schrittweise Agenten-Funktionen hinzufügen, während bestehende API-Endpunkte unverändert erhalten bleiben.

Wie funktioniert die lokale Entwicklung?

Wenn Sie den lokalen Entwicklungsserver mit wrangler dev starten, werden Durable Objects, SQLite und WebSockets vollständig lokal emuliert. Sie können dieselbe API-Oberfläche wie in der Produktion lokal testen und so schnelle Entwicklungs- und Testzyklen ohne Abhängigkeiten von externen Diensten durchführen.