← Vytvářejte agenty na Cloudflare / agents / runtime / communication
Zprávy protokolu
Když se klient WebSocket připojí k Agentovi, framework automaticky odešle několik textových rámců JSON: identitu, stav a seznamy serverů MCP. Tyto protokolové zprávy specifické pro dané připojení můžete u klientů, kteří je neumí zpracovat, potlačit.
Přehled
Při každém novém připojení odešle Agent tři protokolové zprávy:
| Typ zprávy | Obsah |
|---|---|
cf_agent_identity |
Název a třída agenta |
cf_agent_state |
Aktuální stav agenta |
cf_agent_mcp_servers |
Seznam připojených MCP serverů |
Stav a zprávy MCP se také vysílají všem připojením při každé jejich změně.
U většiny webových klientů to nevadí: Client SDK a useAgent hook tyto zprávy zpracovávají automaticky. Někteří klienti ale neumí zpracovat textové rámce JSON:
- Čistě binární klienti : Zařízení MQTT, IoT senzory, vlastní binární protokoly
- Odlehčení klienti : Vestavěné systémy s minimální podporou WebSocket
- Klienti mimo prohlížeč : Hardwarová zařízení připojující se přes WebSocket
U těchto připojení můžete potlačit protokolové zprávy a přitom zachovat vše ostatní (RPC, běžné zprávy, vysílání přes this.broadcast()) funguje normálně.
Potlačení protokolových zpráv
Přepsat shouldSendProtocolMessages pro řízení toho, která připojení dostávají protokolové zprávy. Vraťte false a potlačit je.
import { Agent } from "agents";
export class IoTAgent extends Agent {
shouldSendProtocolMessages(connection, ctx) {
const url = new URL(ctx.request.url);
return url.searchParams.get("protocol") !== "false";
}
}import { Agent, type Connection, type ConnectionContext } from "agents";
export class IoTAgent extends Agent<Env, State> {
shouldSendProtocolMessages(
connection: Connection,
ctx: ConnectionContext,
): boolean {
const url = new URL(ctx.request.url);
return url.searchParams.get("protocol") !== "false";
}
}Tento hook se spouští během onConnect, ještě před odesláním jakýchkoli zpráv. Když vrátí false:
- Ne
cf_agent_identity,cf_agent_state, nebocf_agent_mcp_serverszprávy se odesílají při připojení - Připojení je od této chvíle vyloučeno ze stavu a vysílání MCP
- Volání RPC, běžné
onMessagezpracování athis.broadcast()stále fungují normálně
Používání subprotokolu WebSocket
Můžete také zkontrolovat hlavičku WebSocket subprotokolu, což je standardní způsob vyjednávání protokolů přes WebSocket:
export class MqttAgent extends Agent {
shouldSendProtocolMessages(connection, ctx) {
// MQTT-over-WebSocket clients negotiate via subprotocol
const subprotocol = ctx.request.headers.get("Sec-WebSocket-Protocol");
return subprotocol !== "mqtt";
}
}export class MqttAgent extends Agent<Env, State> {
shouldSendProtocolMessages(
connection: Connection,
ctx: ConnectionContext,
): boolean {
// MQTT-over-WebSocket clients negotiate via subprotocol
const subprotocol = ctx.request.headers.get("Sec-WebSocket-Protocol");
return subprotocol !== "mqtt";
}
}Kontrola stavu protokolu
Použijte isConnectionProtocolEnabled pro kontrolu, zda má připojení povolené protokolové zprávy:
export class MyAgent extends Agent {
@callable()
async getConnectionInfo() {
const { connection } = getCurrentAgent();
if (!connection) return null;
return {
protocolEnabled: this.isConnectionProtocolEnabled(connection),
readonly: this.isConnectionReadonly(connection),
};
}
}export class MyAgent extends Agent<Env, State> {
@callable()
async getConnectionInfo() {
const { connection } = getCurrentAgent();
if (!connection) return null;
return {
protocolEnabled: this.isConnectionProtocolEnabled(connection),
readonly: this.isConnectionReadonly(connection),
};
}
}Co se potlačuje a co ne
Následující tabulka ukazuje, co stále funguje, když jsou pro dané připojení potlačeny zprávy protokolu:
| Akce | Funguje? |
|---|---|
Přijímejte cf_agent_identity při připojení |
Ne |
Přijímejte cf_agent_state při připojení a vysílá |
Ne |
Přijímejte cf_agent_mcp_servers při připojení a vysílá |
Ne |
| Odesílejte a přijímejte běžné zprávy WebSocket | Ano |
Zavolejte @callable() metody RPC |
Ano |
Přijímejte this.broadcast() zprávy |
Ano |
| Odesílejte binární data | Ano |
| Změna stavu agenta přes RPC | Ano |
Kombinace s režimem jen pro čtení
Připojení může být zároveň jen pro čtení a s potlačeným protokolem. To se hodí pro binární zařízení, která mají stav pouze sledovat, ne upravovat:
export class SensorHub extends Agent {
shouldSendProtocolMessages(connection, ctx) {
const url = new URL(ctx.request.url);
// Binary sensors don't handle JSON protocol frames
return url.searchParams.get("type") !== "sensor";
}
shouldConnectionBeReadonly(connection, ctx) {
const url = new URL(ctx.request.url);
// Sensors can only report data via RPC, not modify shared state
return url.searchParams.get("type") === "sensor";
}
@callable()
async reportReading(sensorId, value) {
// This RPC still works for readonly+no-protocol connections
// because it writes to SQL, not agent state
this
.sql`INSERT INTO readings (sensor_id, value, ts) VALUES (${sensorId}, ${value}, ${Date.now()})`;
}
}export class SensorHub extends Agent<Env, SensorState> {
shouldSendProtocolMessages(
connection: Connection,
ctx: ConnectionContext,
): boolean {
const url = new URL(ctx.request.url);
// Binary sensors don't handle JSON protocol frames
return url.searchParams.get("type") !== "sensor";
}
shouldConnectionBeReadonly(
connection: Connection,
ctx: ConnectionContext,
): boolean {
const url = new URL(ctx.request.url);
// Sensors can only report data via RPC, not modify shared state
return url.searchParams.get("type") === "sensor";
}
@callable()
async reportReading(sensorId: string, value: number) {
// This RPC still works for readonly+no-protocol connections
// because it writes to SQL, not agent state
this
.sql`INSERT INTO readings (sensor_id, value, ts) VALUES (${sensorId}, ${value}, ${Date.now()})`;
}
}Oba příznaky jsou uloženy v attachmentu WebSocketu daného připojení a jsou skryté před connection.state : navzájem si nepřekážejí ani nezasahují do uživatelsky definovaného stavu připojení.
Referenční dokumentace API
shouldSendProtocolMessages
Přepisovatelný hook, který určuje, zda připojení bude při navázání dostávat protokolové zprávy.
| Parametr | Typ | Popis |
|---|---|---|
connection |
Connection |
Připojující se klient |
ctx |
ConnectionContext |
Obsahuje požadavek na upgrade |
| Vrací | boolean |
false k potlačení protokolových zpráv |
Výchozí hodnota: vrací true (všechna připojení dostávají protokolové zprávy).
Tento hook se vyhodnotí jednou při připojení. Výsledek se trvale uloží do WebSocket attachmentu daného připojení a přežije hibernace.
isConnectionProtocolEnabled
Zkontroluje, zda má připojení aktuálně povoleny zprávy protokolu.
| Parametr | Typ | Popis |
|---|---|---|
connection |
Connection |
Připojení ke kontrole |
| Vrací | boolean |
true pokud jsou povoleny zprávy protokolu |
Lze bezpečně volat kdykoli, i po probuzení agenta z hibernace.
Jak to funguje
Stav protokolu se ukládá jako interní příznak v příloze WebSocketu daného připojení: stejný mechanismus používá připojení pouze pro čtení. To znamená:
- Přežije hibernaci : příznak se serializuje a obnoví se, jakmile se agent probudí
- Není potřeba žádné čištění : Stav připojení se po jeho uzavření automaticky zahodí
- Nulová režie : žádné databázové tabulky ani dotazy, jen vestavěná příloha připojení
- Bezpečné před uživatelským kódem,
connection.stateaconnection.setState()nikdy nezveřejňujte ani nepřepisujte příznak
Na rozdíl od pouze pro čtení které lze dynamicky přepínat pomocí setConnectionReadonly(), stav protokolu se nastaví jednou při připojení a poté už ho nelze změnit. Aby klient změnil stav protokolu připojení, musí se odpojit a znovu připojit.