INTEGRITY Dokumentace

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:

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:

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á:

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.