INTEGRITY Dokumentace

RPC podřízeného agenta a programová kola

Think funguje jak jako agent nejvyšší úrovně, tak jako podřízený agent. Při použití jako podřízený agent chat() metoda spustí celý tah a streamuje události přes callback.

Pro trvalé přijetí s idempotentním opakováním a pozdější kontrolou stavu viz Programové odesílání. Pro obnovení po vyřazení z paměti si přečtěte Trvalé obnovení.

chat

async chat(
	userMessage: string | UIMessage,
	callback: StreamCallback,
	options?: ChatOptions,
): Promise<void>

StreamCallback

Metoda Když se spustí
onStart(event) Před zahájením práce; zpřístupňuje ID požadavku pro zrušení
onEvent(json) Pro každý streamovaný chunk (serializovaný do JSON UIMessageChunk)
onDone() Po dokončení kola a uložení zprávy asistenta
onError(message) Při chybě během daného kola
onInterrupted() Volitelné. Pokus byl přerušen a naplánované pokračování (v pozdějším isolate) má na starosti konečný výsledek: není dokončeno, není to konečná chyba. Výchozí chování je no-op

onInterrupted je důležité pro chat()-řízené kolo, které je přerušeno a poté se obnoví: RPC promise se vyřeší čistě (izolát je stále aktivní), takže odběratel řídící se pouze čistým vyřešením by to mylně vyhodnotil jako úspěch a finalizoval by jakoukoli částečnou odpověď, kterou už streamoval. Berte to jako stav „nedokončeno, ale ani neúspěšné: odpověď má na starosti navazující pokračování“: ponechte kanál otevřený, zobrazte stav obnovování nebo se znovu připojte, místo abyste finalizovali částečnou odpověď. Přerušení kvůli nasazení nebo evikci izolát ukončí dříve, než k tomu stihne dojít (volající místo toho uvidí přerušení přenosu); onInterrupted popisuje cestu od zaseknutí v izolátu k obnovení.

ChatOptions

Pole Popis
signal AbortSignal pro zrušení tahu uprostřed streamu

Nástroje patří podřízenému agentovi. Trvalé schopnosti definujte pomocí podřízeného agenta getTools(), rozšíření, nástroje MCP nebo schémata klientských nástrojů. Starší volající, kteří předávají options.tools na chat() obdrží varování a hodnota se ignoruje.

Příklad: rodič volá potomka

import { Think } from "@cloudflare/think";

export class ParentAgent extends Think {
	getModel() {
		/* ... */
	}

	async delegateToChild(task) {
		const child = await this.subAgent(ChildAgent, "child-1");

		const chunks = [];
		await child.chat(task, {
			onStart: (event) => {
				console.log("Child started:", event.requestId);
			},
			onEvent: (json) => {
				chunks.push(json);
			},
			onDone: () => {
				console.log("Child completed");
			},
			onError: (error) => {
				console.error("Child failed:", error);
			},
		});

		return chunks;
	}
}

export class ChildAgent extends Think {
	getModel() {
		/* ... */
	}

	getSystemPrompt() {
		return "You are a research assistant. Analyze data and report findings.";
	}
}
import { Think } from "@cloudflare/think";
import type { StreamCallback } from "@cloudflare/think";

export class ParentAgent extends Think<Env> {
	getModel() {
		/* ... */
	}

	async delegateToChild(task: string) {
		const child = await this.subAgent(ChildAgent, "child-1");

		const chunks: string[] = [];
		await child.chat(task, {
			onStart: (event) => {
				console.log("Child started:", event.requestId);
			},
			onEvent: (json) => {
				chunks.push(json);
			},
			onDone: () => {
				console.log("Child completed");
			},
			onError: (error) => {
				console.error("Child failed:", error);
			},
		});

		return chunks;
	}
}

export class ChildAgent extends Think<Env> {
	getModel() {
		/* ... */
	}

	getSystemPrompt() {
		return "You are a research assistant. Analyze data and report findings.";
	}
}

Rušení kola podřízeného agenta

Použijte onStart a cancelChat() pro bezpečné zrušení RPC napříč hranicí subagenta:

let requestId;

const callback = {
	onStart(event) {
		requestId = event.requestId;
	},
	onEvent(json) {
		// Forward stream chunks.
	},
	onDone() {},
	onError(error) {
		console.error(error);
	},
};

const turn = child.chat("Long analysis task", callback);

// Later, from another RPC call or failure handler:
if (requestId) {
	await child.cancelChat(requestId, "client disconnected");
}

await turn;
let requestId: string | undefined;

const callback: StreamCallback = {
	onStart(event) {
		requestId = event.requestId;
	},
	onEvent(json) {
		// Forward stream chunks.
	},
	onDone() {},
	onError(error) {
		console.error(error);
	},
};

const turn = child.chat("Long analysis task", callback);

// Later, from another RPC call or failure handler:
if (requestId) {
	await child.cancelChat(requestId, "client disconnected");
}

await turn;

Pokud volající a volaný nejsou odděleni pomocí Workers RPC, můžete také předat AbortSignal pro zrušení uprostřed streamu:

const controller = new AbortController();
setTimeout(() => controller.abort(), 30_000);

await child.chat("Long analysis task", callback, {
	signal: controller.signal,
});
const controller = new AbortController();
setTimeout(() => controller.abort(), 30_000);

await child.chat("Long analysis task", callback, {
	signal: controller.signal,
});

cancelChat(requestId, reason?) nic neudělá, pokud je kolo již dokončené nebo ID požadavku není známé. Při přerušení zůstává částečná zpráva asistenta uložena.

saveMessages

Vkládejte zprávy a spouštějte tah modelu bez připojení WebSocket. Použijte pro naplánované odpovědi, tahy spouštěné webhookem, proaktivní agenty nebo řetězení od onChatResponse.

async saveMessages(
	messages:
		| UIMessage[]
		| ((current: UIMessage[]) => UIMessage[] | Promise<UIMessage[]>),
	options?: SaveMessagesOptions,
): Promise<SaveMessagesResult>

Vrátí { requestId, status, error? } kde status je "completed", "error", "skipped", nebo "aborted".

status Kdy
"completed" Kolo doběhlo do konce.
"error" Kolo bylo zahájeno, ale stream nahlásil chybu. error obsahuje chybovou zprávu streamu, je-li k dispozici.
"skipped" Kolo znehodnoceno za běhu, například pomocí chat-clear; zpráva uživatele uložena, model se nespustil.
"aborted" Kolo zrušeno před dokončením přes options.signal nebo chat-request-cancel. Částečné fragmenty odpovědi asistenta se přesto uložily.

Předejte options.signal pro zrušení programového tahu z Durable Object, který jej spouští. AbortSignal nemůže překročit hranice RPC Durable Object a signál se při hibernaci neukládá.

Statické zprávy

await this.saveMessages([
	{
		id: crypto.randomUUID(),
		role: "user",
		parts: [{ type: "text", text: "Time for your daily summary." }],
	},
]);
await this.saveMessages([
	{
		id: crypto.randomUUID(),
		role: "user",
		parts: [{ type: "text", text: "Time for your daily summary." }],
	},
]);

Podoba funkce

Pokud je více saveMessages volání se řadí do fronty, funkční forma se pak spustí s nejnovějšími zprávami až ve chvíli, kdy kolo skutečně začne:

await this.saveMessages((current) => [
	...current,
	{
		id: crypto.randomUUID(),
		role: "user",
		parts: [{ type: "text", text: "Continue your analysis." }],
	},
]);
await this.saveMessages((current) => [
	...current,
	{
		id: crypto.randomUUID(),
		role: "user",
		parts: [{ type: "text", text: "Continue your analysis." }],
	},
]);

Naplánované odpovědi

Spusťte opakující se kolo promptu pomocí getScheduledTasks():

export class MyAgent extends Think {
	getModel() {
		/* ... */
	}

	getScheduledTasks() {
		return {
			dailyReport: {
				schedule: "every day at 09:00",
				timezone: "UTC",
				prompt: "Generate the daily report.",
			},
		};
	}
}
export class MyAgent extends Think<Env> {
	getModel() {
		/* ... */
	}

	getScheduledTasks() {
		return {
			dailyReport: {
				schedule: "every day at 09:00",
				timezone: "UTC",
				prompt: "Generate the daily report.",
			},
		};
	}
}

Zřetězení z onChatResponse

Spusťte navazující kolo po dokončení toho aktuálního:

async onChatResponse(result: ChatResponseResult) {
	if (result.status === "completed" && this.needsFollowUp(result.message)) {
		await this.saveMessages([{
			id: crypto.randomUUID(),
			role: "user",
			parts: [{ type: "text", text: "Now summarize what you found." }],
		}]);
	}
}

continueLastTurn

Spusťte další volání modelu po poslední zprávě asistenta, aniž byste vkládali novou zprávu uživatele. Think uloží výsledek jako novou zprávu asistenta s continuation: true; nepřipojuje části k existující zprávě asistenta.

protected async continueLastTurn(
	body?: Record<string, unknown>,
	options?: SaveMessagesOptions,
): Promise<SaveMessagesResult>

Vrátí { requestId, status: "skipped" } pokud poslední zpráva není zprávou asistenta. Volitelný body parametr přepisuje uložené tělo pro toto pokračování. Předejte options.signal pro zrušení pokračování během jeho běhu.

abortRequest a abortAllRequests

Zrušte probíhající kola chatu zevnitř Durable Object:

protected abortRequest(requestId: string, reason?: unknown): void
protected abortAllRequests(): void

Použijte abortRequest() když znáte ID požadavku. Použijte abortAllRequests() pro jednoúčelové pomocné funkce, které mají zrušit právě probíhající kolo, ať je jakékoli. Upřednostněte SaveMessagesOptions.signal pro programová kola, pokud můžete signál předat přímo v místě volání.