← Vytvářejte agenty na Cloudflare / agents / harnesses / think
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);
},
});clientToolszaregistruje schémata nástrojů pro dané kolo, stejně jako WebSocketclientTools.onClientToolCallprovede volání klientského nástroje a vrátí jeho výstup. Model může zavolat klientský nástroj, přijmout výsledek a pokračovat, to vše v rámci jedinéhochat()volání.
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í
- Obnovení: schémata a
onClientToolCallexecutoru platí jen pro dané kolo a nikdy se neukládají (executor je živá RPC reference, která zaniká spolu s izolátem, a na rozdíl od cesty přes WebSocket zde není žádný klient, který by mohl znovu přehráttool-resultpo vyřazení z paměti). Pokud vyřazení přeruší tah ve chvíli, kdy je volání nástroje na straně klienta ještě zpracováváno, obnovení chatu osiřelé volání označí jako chybné (stejně jako by šlo o serverový nástroj) a model pokračuje dál. Pro čisté opětovné spuštění rodič znovu zavoláchat()hodnotouclientToolsaonClientToolCallznovu. - Chyby: v případě, že
onClientToolCallvyvolá výjimku, selhání se zobrazí modelu jako chyba nástroje (output-error) a kolo pokračuje dál, nedojde k jeho pádu. - Serializace: hodnotu vrácenou z
onClientToolCallse stává výstupem nástroje, proto musí být serializovatelný do JSON (putuje zpět přes RPC do kontextu modelu). - Žádná schvalovací brána: Klientské nástroje RPC se spouštějí okamžitě prostřednictvím
onClientToolCall. Schvalovací postup přes WebSocket (needsApproval) se na této cestě neuplatní. Pokud ji potřebujete, zajistěte kontrolu spouštění přímo ve vlastním exekutoru. - Priorita názvu: klientské nástroje se sloučí až po serverových nástrojích, takže klientský nástroj se stejným názvem jako serverový nástroj (například workspace tool) ho pro dané kolo přepíše, stejně jako u WebSocket cesty.
- Přerušení: přerušení tahu pomocí
signalzastaví smyčku, ale rozběhléonClientToolCallse sám o sobě neruší, kolo končí až po vyřešení aktuálního volá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í.