INTEGRITY Dokumentace

Klientské nástroje

Think podporuje nástroje, které se spouští v prohlížeči. Klient odešle serializovatelná schémata nástrojů v těle chatového požadavku, Think je sloučí se serverovými nástroji, a když LLM zavolá klientský nástroj, volání se přesměruje k provedení klientovi.

Definování klientských nástrojů

Pro dynamické nástroje na straně klienta předejte tools na useAgentChat. Nástroje s execute funkce jsou na serveru registrovány jako nástroje spouštěné klientem:

const { messages, sendMessage } = useAgentChat({
	agent,
	tools: {
		getUserTimezone: {
			description: "Get the user's timezone from their browser",
			parameters: {},
			execute: async () => {
				return Intl.DateTimeFormat().resolvedOptions().timeZone;
			},
		},
		getClipboard: {
			description: "Read text from the user's clipboard",
			parameters: {},
			execute: async () => {
				return navigator.clipboard.readText();
			},
		},
	},
});
const { messages, sendMessage } = useAgentChat({
	agent,
	tools: {
		getUserTimezone: {
			description: "Get the user's timezone from their browser",
			parameters: {},
			execute: async () => {
				return Intl.DateTimeFormat().resolvedOptions().timeZone;
			},
		},
		getClipboard: {
			description: "Read text from the user's clipboard",
			parameters: {},
			execute: async () => {
				return navigator.clipboard.readText();
			},
		},
	},
});

Klientské nástroje jsou nástroje bez execute funkci na serveru, mají pouze schéma. Když LLM vytvoří volání nástroje pro některý z nich, Think ho nasměruje ke klientovi.

U většiny aplikací je vhodnější definovat nástroje na serveru a používat onToolCall pro spouštění pouze v prohlížeči. tools možnost je nejužitečnější pro SDK nebo platformy, kde prohlížeč rozhoduje o dostupné sadě nástrojů za běhu.

Klientské nástroje přes RPC podřízeného agenta chat() cesta

Když nadřazený agent deleguje na podřízeného agenta Think přes RPC s chat() (namísto WebSocketu prohlížeče), neexistuje žádný WebSocket, který by přenášel clientTools nebo pro odeslání výsledků nástrojů zpět. Předejte je přes ChatOptions místo toho:

await child.chat(message, callback, {
	signal,
	clientTools: [
		{
			name: "get_user_timezone",
			description: "Get the caller's timezone",
			parameters: { type: "object" },
		},
	],
	onClientToolCall: async ({ toolName, input }) => {
		// Run the client tool wherever the parent can — return its output.
		return runClientTool(toolName, input);
	},
});
await child.chat(message, callback, {
	signal,
	clientTools: [
		{
			name: "get_user_timezone",
			description: "Get the caller's timezone",
			parameters: { type: "object" },
		},
	],
	onClientToolCall: async ({ toolName, input }) => {
		// Run the client tool wherever the parent can — return its output.
		return runClientTool(toolName, input);
	},
});

Pokud vynecháte onClientToolCall, nástroje jsou zaregistrované, ale nemají žádný výsledek: volání modelu se zobrazí prostřednictvím stream callbacku a kolo skončí visícím voláním nástroje (stream callback RPC nemá vlastní vstupní kanál pro výsledek). Zadejte onClientToolCall kdykoli chcete, aby se dokončil celý cyklus požadavku a odpovědi.

Poznámky k chování

Postup schvalování

Zpracujte spouštění nástrojů na straně prohlížeče na klientovi pomocí onToolCall:

useAgentChat({
	agent,
	onToolCall: async ({ toolCall, addToolOutput }) => {
		if (toolCall.toolName === "read") {
			const result = await readFromBrowser(toolCall.input);
			addToolOutput({
				toolCallId: toolCall.toolCallId,
				output: result,
			});
		}
	},
});
useAgentChat({
	agent,
	onToolCall: async ({ toolCall, addToolOutput }) => {
		if (toolCall.toolName === "read") {
			const result = await readFromBrowser(toolCall.input);
			addToolOutput({
				toolCallId: toolCall.toolCallId,
				output: result,
			});
		}
	},
});

Automatické pokračování

Jakmile je přijat výsledek klientského nástroje, Think automaticky pokračuje v konverzaci bez nové zprávy uživatele. Navazující kolo má continuation: true v TurnContext, který můžete použít v beforeTurn pro úpravu výběru modelu nebo nástrojů.

Když kolo vytvoří najednou několik volání nástrojů na straně klienta, Think čeká na all svých výsledků před zahájením jediného pokračování, místo aby se pro každý výsledek spouštělo samostatné pokračování. Okamžitý požadavek na obnovení, který přijde ve chvíli, kdy už jedno pokračování čeká na vyřízení, se připojí k tomuto čekajícímu pokračování, místo aby spustil další duplicitní pokračování, a na straně serveru needsApproval pokračování se spolehlivě obnoví, jakmile se schválení zaznamená.

Přežít restarty při čekání na člověka

Durable Object může být kdykoli vyřazen z paměti, a to i ve chvíli, kdy je kolo pozastaveno na výzvě ke schválení nebo na volání nástroje na straně klienta. Think trvalé obnovení je vždy zapnuté. SDK takové kolo považuje za čekající na člověka, nikoli za zaseknuté. Kolo pozastaví, místo aby ho ukončilo chybou. Konverzace pokračuje, jakmile uživatel nakonec schválí akci nebo je k dispozici výsledek nástroje.

Které interakce jsou vyňaty z rozpočtů na zotavení, zjistíte v Kola čekající na člověka nejsou uzavřená.

Souběžnost zpráv

messageConcurrency vlastnost řídí, jak se chovají překrývající se odeslání uživatele, když je kolo konverzace již aktivní.

Strategie Chování
"queue" Zařadí každé podání do fronty a zpracuje je v pořadí. Výchozí.
"latest" Ponechte pouze nejnovější překrývající se odeslání; nahrazená odeslání si i nadále uchovávají své uživatelské zprávy, ale nezahajují kolo modelu
"merge" Zařadí překrývající se podání do fronty a poté sloučí jejich koncové uživatelské zprávy do jednoho společného kola ještě před spuštěním posledního zařazeného kola
"drop" Překrývající se odeslání zcela ignorujte. Zprávy se neukládají.
{ strategy: "debounce", debounceMs?: number } Poslední hodnota na konci intervalu s tichým oknem (výchozí 750 ms).
import { Think } from "@cloudflare/think";

export class SearchAgent extends Think {
	messageConcurrency = "latest";
	getModel() {
		/* ... */
	}
}
import { Think } from "@cloudflare/think";
import type { MessageConcurrency } from "@cloudflare/think";

export class SearchAgent extends Think<Env> {
	override messageConcurrency: MessageConcurrency = "latest";
	getModel() {
		/* ... */
	}
}

Vysílání mezi kartami

Think vysílá streamované odpovědi všem připojeným klientům WebSocket. Pokud je ke stejnému agentovi připojeno více karet prohlížeče, všechny karty vidí streamovanou odpověď v reálném čase. Stavy volání nástrojů (čekající, výsledek, schválení) se vysílají do všech karet.

Programové chat() tahy a clearMessages() také vysílají aktualizace zpráv připojeným useAgentChat klientů, takže klienti v prohlížeči zůstávají synchronizovaní bez nutnosti nového připojení.