INTEGRITY Dokumentace

Think

@cloudflare/think umožňuje vytvořit stavového chatovacího agenta AI, tedy takového, který streamuje odpovědi, pamatuje si konverzaci a volá nástroje, a to rozšířením jediné základní třídy. Modelu předáte getModel(), a o zbytek životního cyklu chatu se postará Think: agentní smyčku (model volá nástroje, čte výsledky a pokračuje, dokud nemá odpověď), perzistenci zpráv, streamování, klientské nástroje, obnovení streamu a rozšíření, to vše na bázi Durable Object SQLite.

Think funguje jak jako agent nejvyšší úrovně (WebSocket chat pro klientské prohlížeče prostřednictvím useAgentChat) a sub-agent (podřízený agent, který jiný agent řídí přes RPC prostřednictvím chat()).

Rychlý start

Instalovat

npm i @cloudflare/think @cloudflare/ai-chat agents ai @cloudflare/shell zod workers-ai-provider

Think podporuje AI SDK v6 a v7. Použijte ai@^6 hodnotou @ai-sdk/react@^3, nebo použijte ai@^7 hodnotou @ai-sdk/react@^4. V celém projektu udržujte balíčky AI SDK na shodných hlavních verzích.

Server

import { Think } from "@cloudflare/think";
import { createWorkersAI } from "workers-ai-provider";
import { routeAgentRequest } from "agents";

export class MyAgent extends Think {
	getModel() {
		return createWorkersAI({ binding: this.env.AI })(
			"@cf/moonshotai/kimi-k2.6",
		);
	}
}

export default {
	async fetch(request, env) {
		return (
			(await routeAgentRequest(request, env)) ||
			new Response("Not found", { status: 404 })
		);
	},
};
import { Think } from "@cloudflare/think";
import { createWorkersAI } from "workers-ai-provider";
import { routeAgentRequest } from "agents";

export class MyAgent extends Think<Env> {
	getModel() {
		return createWorkersAI({ binding: this.env.AI })(
			"@cf/moonshotai/kimi-k2.6",
		);
	}
}

export default {
	async fetch(request: Request, env: Env) {
		return (
			(await routeAgentRequest(request, env)) ||
			new Response("Not found", { status: 404 })
		);
	},
} satisfies ExportedHandler<Env>;

To je vše. Think se stará o protokol WebSocket chatu, perzistenci zpráv, agentickou smyčku, sanitizaci zpráv, obnovení streamu, podporu klientských nástrojů a nástroje pro práci se soubory pracovního prostoru.

Klient

import { useAgent } from "agents/react";
import { useAgentChat } from "@cloudflare/ai-chat/react";

function Chat() {
	const agent = useAgent({ agent: "MyAgent" });
	const { messages, sendMessage, status } = useAgentChat({ agent });

	return (
		<div>
			{messages.map((msg) => (
				<div key={msg.id}>
					<strong>{msg.role}:</strong>
					{msg.parts.map((part, i) =>
						part.type === "text" ? <span key={i}>{part.text}</span> : null,
					)}
				</div>
			))}

			<form
				onSubmit={(e) => {
					e.preventDefault();
					const input = e.currentTarget.elements.namedItem("input");
					sendMessage({ text: input.value });
					input.value = "";
				}}
			>
				<input name="input" placeholder="Send a message..." />
				<button type="submit">Send</button>
			</form>
		</div>
	);
}
import { useAgent } from "agents/react";
import { useAgentChat } from "@cloudflare/ai-chat/react";

function Chat() {
	const agent = useAgent({ agent: "MyAgent" });
	const { messages, sendMessage, status } = useAgentChat({ agent });

	return (
		<div>
			{messages.map((msg) => (
				<div key={msg.id}>
					<strong>{msg.role}:</strong>
					{msg.parts.map((part, i) =>
						part.type === "text" ? <span key={i}>{part.text}</span> : null,
					)}
				</div>
			))}

			<form
				onSubmit={(e) => {
					e.preventDefault();
					const input = e.currentTarget.elements.namedItem(
						"input",
					) as HTMLInputElement;
					sendMessage({ text: input.value });
					input.value = "";
				}}
			>
				<input name="input" placeholder="Send a message..." />
				<button type="submit">Send</button>
			</form>
		</div>
	);
}

Konfigurace

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  // Set this to today's date
  "compatibility_date": "2026-08-28",
  "compatibility_flags": [
    "nodejs_compat"
  ],
  "ai": {
    "binding": "AI"
  },
  "durable_objects": {
    "bindings": [
      {
        "class_name": "MyAgent",
        "name": "MyAgent"
      }
    ]
  },
  "migrations": [
    {
      "new_sqlite_classes": [
        "MyAgent"
      ],
      "tag": "v1"
    }
  ]
}
# Set this to today's date
compatibility_date = "2026-08-28"
compatibility_flags = ["nodejs_compat"]

[ai]
binding = "AI"

[[durable_objects.bindings]]
class_name = "MyAgent"
name = "MyAgent"

[[migrations]]
new_sqlite_classes = ["MyAgent"]
tag = "v1"

Trasování

Think používá wrapAISDK() interně k instrumentaci kol modelu, volání nástrojů a segmentů životního cyklu schvalování. Není třeba obalovat AI SDK ani konfigurovat adaptér. Pro odeslání invoke_agent, chat, execute_tool, a tool_approval spany do Workers Observability, zapněte Workers traces:

{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "observability": {
    "traces": {
      "enabled": true
    }
  }
}
[observability.traces]
enabled = true

Trasování se zobrazuje v zobrazení Agents na Cloudflare Dashboard. Můžete si prohlédnout konverzace a časové osy trasování. Chcete-li trasování vypnout, nastavte observability.traces.enabled na false. Třídu agenta Think není potřeba měnit.

Atributy spanů, ovládání payloadu, export trasování a přímé nastavení AI SDK v6 nebo v7 najdete v Trasování.

Think oproti AIChatAgent

Jak Think, tak AIChatAgent rozšiřte Agent a mluvit stejným cf_agent_chat_* protokol WebSocket. Slouží k odlišným účelům.

AIChatAgent je adaptér protokolu. Přepište onChatMessage a odpovídají za volání streamText, propojuje nástroje, převádí zprávy a vrací Response. AIChatAgent řeší podpůrnou logiku: perzistenci zpráv, streamování, přerušení a obnovení, ale volání LLM je zcela na vás.

Think je framework s pevně danými konvencemi. Rozhoduje za vás: getModel() vrátí model, getSystemPrompt() nebo configureSession() nastaví prompt, getTools() vrátí nástroje. Výchozí onChatMessage spouští kompletní agentní smyčku. Přepisujete jednotlivé části, ne celý pipeline.

Aspekt AIChatAgent Think
Minimální podtřída ~15 řádků (přenosový streamText + nástroje + systémový prompt + odpověď) 3 řádky (getModel() pouze)
Úložiště Plochá tabulka SQL Session: stromově strukturované zprávy, kontextové bloky, komprimace, FTS5
Regenerace Destruktivní (stará odpověď se smaže) Nedestruktivní větvení (staré odpovědi zůstávají zachovány)
Správa kontextu Ruční Kontextové bloky s trvalou pamětí zapisovatelnou LLM
RPC podřízeného agenta Není vestavěné chat() hodnotou StreamCallback
Programová kola saveMessages() saveMessages(), submitMessages(), continueLastTurn()
Komprimace maxPersistedMessages (odstraní nejstarší) Nedestruktivní souhrny pomocí překryvů
Hledat Není k dispozici Fulltextové vyhledávání FTS5 v rámci relace i napříč relacemi

Kdy použít AIChatAgent

Kdy použít Think

Zvolte API pro kola

Think nabízí několik způsobů, jak kolo zahájit nebo v něm pokračovat. Všechny vedou přes jediný veřejný vstupní bod: runTurn(options) : Starší metody zůstávají zachovány jako praktické zkratky.

runTurn()

runTurn() je jednotné API pro připuštění kola. Jedna metoda, tři režimy, které se volí podle options.mode:

Režim Kdy použít Vrací Zkratka pro
"wait" (výchozí) Volající může počkat, dokud odpověď modelu nebude hotová Promise<TurnResult> saveMessages()
"submit" Volající potřebuje rychlé a trvalé přijetí požadavku a stav zjistit až později Promise<SubmitMessagesResult> submitMessages()
"stream" Volající chce, aby se odpověď streamovala do callbacku (RPC) Promise<void> chat()

input přijímá řetězec, UIMessage, pole zpráv nebo, v wait a stream režimech, funkce (current) => UIMessage[] se vyhodnotí při přijetí. (submit nepřijímá vstup funkce.)

export class Assistant extends Think {
	async examples(inboundEventId) {
		// wait — block for the result
		const result = await this.runTurn({ input: "Summarize the latest thread" });
		if (result.status === "completed") {
			// result.message is the assistant message; result.continuation is false
		}

		// submit — durable acceptance, check status later
		const submission = await this.runTurn({
			mode: "submit",
			input: "Process this webhook",
			idempotencyKey: inboundEventId, // dedupe; safe to retry
		});
		// submission.accepted is true on first accept; submission.status is "pending"

		// stream — drive a callback (the same surface as chat())
		await this.runTurn({
			mode: "stream",
			input: "Stream me",
			callback: {
				onStart({ requestId }) {},
				onEvent(json) {}, // UIMessageChunk JSON
				onDone() {},
				onError(error) {},
			},
		});

		// continuation — continue the last assistant turn instead of sending input
		await this.runTurn({ continuation: true });
	}
}
export class Assistant extends Think<Env> {
	async examples(inboundEventId: string) {
		// wait — block for the result
		const result = await this.runTurn({ input: "Summarize the latest thread" });
		if (result.status === "completed") {
			// result.message is the assistant message; result.continuation is false
		}

		// submit — durable acceptance, check status later
		const submission = await this.runTurn({
			mode: "submit",
			input: "Process this webhook",
			idempotencyKey: inboundEventId, // dedupe; safe to retry
		});
		// submission.accepted is true on first accept; submission.status is "pending"

		// stream — drive a callback (the same surface as chat())
		await this.runTurn({
			mode: "stream",
			input: "Stream me",
			callback: {
				onStart({ requestId }) {},
				onEvent(json) {}, // UIMessageChunk JSON
				onDone() {},
				onError(error) {},
			},
		});

		// continuation — continue the last assistant turn instead of sending input
		await this.runTurn({ continuation: true });
	}
}

Klíčové chování:

runTurn je exportován spolu s typy pro jeho možnosti a výsledek: RunTurnOptions, RunTurnWait, RunTurnSubmit, RunTurnStream, TurnInputMessages, a TurnResult.

Vyberte zkratku

Tabulka níže přiřazuje ke každému scénáři nejpřímější volání. Každá zkratka má nezměněnou signaturu, sáhněte po ní, když chcete užší rozhraní, nebo použijte runTurn() když chcete jeden mentální model.

Případ použití API
Uživatel v prohlížeči odesílá chatové zprávy useAgentChat přes chatovací protokol WebSocket
Kód serveru může počkat na odpověď modelu saveMessages()
Kód serveru potřebuje rychlé trvalé přijetí a pozdější stav submitMessages()
Kód by měl vytvářet opakující se kola řízená promptem nebo handlery getScheduledTasks()
Nadřazený kód potřebuje přímé streamované RPC ke konkrétnímu podřízenému agentovi subAgent(...).chat()
Nadřazený agent deleguje práci na zachovaného podřízeného agenta agentTool() nebo runAgentTool()
Obklopte kolo idempotentními vedlejšími efekty spravovanými aplikací startFiber()
Koordinace vícekrokové trvalé orchestrace Workflows
Přidání kontextu nebo zpráv bez zahájení kola modelu addMessages()
Pokročilá podtřída nebo kód pro obnovení pokračuje v kole asistenta continueLastTurn()

Použijte saveMessages() když volající vlastní spouštěč a může počkat na dokončení kola. Použijte submitMessages() když by nejednoznačnost časového limitu činila opakované pokusy nebezpečnými.

Přidání zpráv bez kola

Použijte addMessages() k zápisu do přepisu bez před začátkem kola modelu: pro import předchozí historie nebo vložení kontextu na pozadí, který by měl být vidět v následujícím kole:

export class Assistant extends Think {
	async importContext() {
		await this.addMessages([
			{
				id: crypto.randomUUID(),
				role: "user",
				parts: [{ type: "text", text: "Imported context" }],
			},
		]);
	}
}
export class Assistant extends Think<Env> {
	async importContext() {
		await this.addMessages([
			{
				id: crypto.randomUUID(),
				role: "user",
				parts: [{ type: "text", text: "Imported context" }],
			},
		]);
	}
}

addMessages() se přidá (nebo aktualizuje) do stromu Session:

Podporovaný vzor je „přidat kontext, poté spustit kolo“: zavolejte addMessages(), poté runTurn().

Použijte chat() pro nízkoúrovňové streamování mezi nadřazeným a podřízeným prvkem, pokud váš kód sám řídí přeposílání, rušení a zásady opakovaného přehrání. Použijte Agents jako nástroje když nadřazený model nebo workflow deleguje na podřízeného agenta a chcete zachované běhy podřízených agentů, přehrávání událostí, přemostění přerušení a možnost proklikat se v UI k detailu.

Použijte startFiber() mimo Think, když je trvalou jednotkou úloha aplikace kolem jednoho kola: jednorázové přijetí webhooku, obnovení serializovaného kanálu nebo cíle vlákna, odeslání viditelné odpovědi nebo zaznamenání zásady zotavení na úrovni aplikace. Odesílání do Think řídí přijímání konverzace a serializaci kol; spravovaná vlákna řídí externí přijímání úloh, idempotentní vedlejší efekty a zotavení aplikace.

V této části

Konfigurace

Přepisy konfigurace, dynamická konfigurace a integrace Session.

Nástroje

Nástroje workspace, spouštění kódu, nástroje prohlížeče a rozšíření.

Akce

Server actions s idempotencí, schvalováním, autorizací a přílohami odpovědí.

Kanály

Zásady pro jednotlivé kanály, výběr kanálu a mimopásmová oznámení.

Messengery

Přijímejte a odpovídejte na webhooky messengerů Chat SDK.

Workflows

Trvalé kroky uvažování řízené modelem uvnitř Cloudflare Workflows.

Agent Skills

Instrukce, zdroje a skripty na vyžádání prostřednictvím getSkills().

Poděkování

Design Think je inspirován Pi ↗.

Příklad

Příklad asistenta

Prozkoumejte asistenta Think s více relacemi, směrováním na podřízené agenty, sdíleným pracovním prostorem, MCP, obnovením chatu a GitHub OAuth.