← Vytvářejte agenty na Cloudflare / agents / tools / codemode
Integrace prohlížeče
Použijte @cloudflare/codemode/browser když nástroje vlastní váš prohlížeč a model je musí jen orchestrovat. Tyto nástroje mohou například číst stav stránky, přistupovat k rozhraním API prohlížeče nebo aktualizovat data uložená ve vaší aplikaci.
Code Mode se hodí, když model musí volat několik klientských nástrojů s cykly, podmínkami nebo mezivýsledky. Pro jedinou akci v prohlížeči místo toho použijte standardní nástroj na straně klienta.
Code Mode prezentuje tyto nástroje modelu jako typované funkce. Model napíše jednu asynchronní arrow funkci JavaScriptu, která může volat několik nástrojů, kombinovat jejich výsledky a uplatňovat řídicí strukturu. IframeSandboxExecutor spouští tento vygenerovaný kód v sandboxovaném iframe na stránce.
Tato integrace neposkytuje agentovi kontrolu nad vzdáleným prohlížečem. Pro prohlížení webových stránek, pořizování snímků obrazovky nebo automatizaci stránek pomocí Chrome DevTools Protocol (CDP) si přečtěte Nástroje prohlížeče.
Instalace Code Mode
Nainstalujte balíček do své klientské aplikace:
npm i @cloudflare/codemode @cloudflare/codemode/browser vstupní bod používá JSON Schema a rozhraní API prohlížeče. Nevyžaduje peer závislosti AI SDK ani Zod, které používá @cloudflare/codemode/ai.
Přidání Code Mode do chatovacího UI Agenta
Prohlížeč vytvoří nástroj Code Mode a zaregistruje ho jako dynamický klientský nástroj. Agent obdrží schéma nástroje, ale implementace nástroje zůstává v prohlížeči.
-
Definujte nástroje vlastněné prohlížečem pomocí JSON Schema a
execute.src/browser-tools.jsexport const browserTools = { getPageInfo: { description: "Get information about the current browser page", inputSchema: { type: "object", properties: {}, required: [], }, execute: async () => ({ title: document.title, url: window.location.href, }), }, getSelectionText: { description: "Get the user's current text selection", inputSchema: { type: "object", properties: {}, required: [], }, execute: async () => ({ text: window.getSelection()?.toString() ?? "", }), }, };src/browser-tools.tsimport type { JsonSchemaExecutableToolDescriptors } from "@cloudflare/codemode/browser"; export const browserTools: JsonSchemaExecutableToolDescriptors = { getPageInfo: { description: "Get information about the current browser page", inputSchema: { type: "object", properties: {}, required: [] }, execute: async () => ({ title: document.title, url: window.location.href }) }, getSelectionText: { description: "Get the user's current text selection", inputSchema: { type: "object", properties: {}, required: [] }, execute: async () => ({ text: window.getSelection()?.toString() ?? "" }) } };JSON Schema poskytuje typy zobrazené modelu.
createBrowserCodeTool()nepoužívá schéma k ověřování argumentů za běhu. Neověřené vstupy validujte uvnitř každéexecutefunkci, když je to potřeba. -
Vytvořte deskriptor Code Mode s executorem iframe.
src/codemode-tool.jsimport { IframeSandboxExecutor, createBrowserCodeTool, } from "@cloudflare/codemode/browser"; import { browserTools } from "./browser-tools"; export const codemodeTool = createBrowserCodeTool({ tools: browserTools, executor: new IframeSandboxExecutor(), });src/codemode-tool.tsimport { IframeSandboxExecutor, createBrowserCodeTool } from "@cloudflare/codemode/browser"; import { browserTools } from "./browser-tools"; export const codemodeTool = createBrowserCodeTool({ tools: browserTools, executor: new IframeSandboxExecutor() });createBrowserCodeTool()vrátí obyčejný deskriptor s názvemcodemode. Jeho popis obsahuje vygenerované definice TypeScript pro nástroje prohlížeče. Jeho vstup obsahuje JavaScript vygenerovaný modelem vcodevlastnost.executormožnost je volitelná. Pokud je vynechána,createBrowserCodeTool()vytvoříIframeSandboxExecutors výchozím nastavením. -
Zaregistrujte deskriptor pomocí
useAgentChat()a provádět volání nástrojů na straně klienta.src/client.jsximport { useAgentChat } from "@cloudflare/ai-chat/react"; import { useAgent } from "agents/react"; import { useMemo } from "react"; import { codemodeTool } from "./codemode-tool"; function BrowserCodeModeChat() { const agent = useAgent({ agent: "browser-codemode" }); const tools = useMemo( () => ({ codemode: { description: codemodeTool.description, parameters: codemodeTool.inputSchema, execute: (input) => codemodeTool.execute(input), }, }), [], ); const { messages, sendMessage } = useAgentChat({ agent, tools, onToolCall: async ({ toolCall, addToolOutput }) => { const tool = tools[toolCall.toolName]; if (!tool?.execute) return; try { const output = await tool.execute(toolCall.input); addToolOutput({ toolCallId: toolCall.toolCallId, output, }); } catch (error) { addToolOutput({ toolCallId: toolCall.toolCallId, state: "output-error", errorText: error instanceof Error ? error.message : String(error), }); } }, }); // Render messages and call sendMessage() from your chat UI. }src/client.tsximport { useAgentChat, type AITool } from "@cloudflare/ai-chat/react"; import { useAgent } from "agents/react"; import { useMemo } from "react"; import { codemodeTool } from "./codemode-tool"; function BrowserCodeModeChat() { const agent = useAgent({ agent: "browser-codemode" }); const tools = useMemo<Record<string, AITool>>( () => ({ codemode: { description: codemodeTool.description, parameters: codemodeTool.inputSchema, execute: (input) => codemodeTool.execute(input as { code: string }) } }), [] ); const { messages, sendMessage } = useAgentChat({ agent, tools, onToolCall: async ({ toolCall, addToolOutput }) => { const tool = tools[toolCall.toolName]; if (!tool?.execute) return; try { const output = await tool.execute(toolCall.input); addToolOutput({ toolCallId: toolCall.toolCallId, output }); } catch (error) { addToolOutput({ toolCallId: toolCall.toolCallId, state: "output-error", errorText: error instanceof Error ? error.message : String(error) }); } } }); // Render messages and call sendMessage() from your chat UI. }useAgentChat()odešle Agentovi registrované schéma nástroje na straně klienta. Když model zavolácodemode,onToolCallprovede deskriptor v prohlížeči a přidá jeho výstup do konverzace. -
Na straně Agenta převeďte klientská schémata na nástroje modelu.
src/server.jsimport { AIChatAgent, createToolsFromClientSchemas } from "@cloudflare/ai-chat"; import { convertToModelMessages, stepCountIs, streamText } from "ai"; import { createWorkersAI } from "workers-ai-provider"; export class BrowserCodemode extends AIChatAgent { async onChatMessage(_onFinish, options) { const workersai = createWorkersAI({ binding: this.env.AI }); const result = streamText({ model: workersai("@cf/moonshotai/kimi-k2.7-code"), system: "Use the codemode tool to write JavaScript that calls browser-provided tools.", messages: await convertToModelMessages(this.messages), tools: createToolsFromClientSchemas(options?.clientTools), stopWhen: stepCountIs(10), }); return result.toUIMessageStreamResponse(); } }src/server.tsimport { AIChatAgent, createToolsFromClientSchemas } from "@cloudflare/ai-chat"; import { convertToModelMessages, stepCountIs, streamText } from "ai"; import { createWorkersAI } from "workers-ai-provider"; export class BrowserCodemode extends AIChatAgent<Env> { async onChatMessage( _onFinish?: unknown, options?: { clientTools?: Parameters<typeof createToolsFromClientSchemas>[0]; } ) { const workersai = createWorkersAI({ binding: this.env.AI }); const result = streamText({ model: workersai("@cf/moonshotai/kimi-k2.7-code"), system: "Use the codemode tool to write JavaScript that calls browser-provided tools.", messages: await convertToModelMessages(this.messages), tools: createToolsFromClientSchemas(options?.clientTools), stopWhen: stepCountIs(10) }); return result.toUIMessageStreamResponse(); } }Agent oznámí modelu schéma poskytnuté klientem. Nespouští vygenerovaný kód ani implementace nástroje prohlížeče.
Pokud se sada nástrojů prohlížeče za běhu změní, vytvořte nový deskriptor Code Mode a zaregistrujte aktualizovaný deskriptor ve vrstvě nástrojů klienta.
Spouštění a zabezpečení iframe
IframeSandboxExecutor vytvoří pro každé spuštění skrytý iframe. Tento iframe používá sandbox="allow-scripts" a přijímá vygenerovaný kód prostřednictvím postMessage. Volání nástrojů se vracejí na rodičovskou stránku, která spustí odpovídající nástroj vlastněný prohlížečem execute .
Zprávy jsou omezeny na aktuální iframe a spouštěcí nonce. Executor po dokončení, selhání nebo vypršení časového limitu odstraní iframe i posluchač zpráv.
Executor přijímá tyto možnosti:
| Možnost | Typ | Výchozí | Chování |
|---|---|---|---|
timeout |
number |
30000 |
Ukončí provedení po uplynutí zadaného počtu milisekund. |
csp |
string |
default-src 'none'; script-src 'unsafe-inline' 'unsafe-eval'; |
Nastavuje zásady zabezpečení obsahu (CSP) pro dokument iframe. |
Výchozí CSP blokuje všechny zdroje kromě vložených a vyhodnocovaných skriptů potřebných ke spuštění vygenerovaného kódu. Vlastní zásadu předejte pouze tehdy, pokud váš vygenerovaný kód potřebuje další možnosti iframe.
Uvolňování direktiv, jako jsou connect-src, img-src, nebo form-action může umožnit, aby vygenerovaný kód iframe komunikoval s externími systémy. Tento kód by mohl vystavit hodnoty vracené nástroji prohlížeče. Omezte cílové adresy odchozí komunikace na nezbytné minimum a nedávejte tajné údaje do výsledků nástrojů. Nástroje vlastněné prohlížečem se spouštějí odděleně na rodičovské stránce s možnostmi, které poskytuje jejich implementace.
Omezení schvalování
createBrowserCodeTool() vyloučí libovolný nástroj, jehož needsApproval hodnota je true nebo funkci. Code Mode nepozastavuje běh iframe kvůli žádosti o schválení těchto nástrojů.
Akce podléhající schválení ponechte mimo deskriptor Code Mode. Zaregistrujte je jako standardní nástroje a použijte useAgentChat() postup schvalování místo toho.