Skip to main content
Agents handle both HTTP requests and WebSocket connections, giving you flexibility to build REST APIs, real-time applications, or hybrid architectures.

Overview

Every agent can respond to:
  • HTTP requests via onRequest() - REST APIs, webhooks, file uploads
  • WebSocket connections via onConnect(), onMessage(), onClose() - Real-time bidirectional communication

Lifecycle Hooks

Agents have several lifecycle hooks that are called at different points:

Lifecycle Flow

HTTP Requests

Handle HTTP requests with onRequest(). This is called for any non-WebSocket request to your agent.

Common HTTP Patterns

WebSocket Connections

WebSockets enable real-time bidirectional communication between clients and your agent.

Connection Lifecycle

The Connection Object

Each WebSocket connection is represented by a Connection object:
string
Unique connection identifier
string
The agent instance name this connection belongs to
TState | null
Per-connection state (read-only, use setState to update)
(state: TState | ((prev: TState | null) => TState)) => void
Update connection state
(message: string | ArrayBuffer) => void
Send a message to this connection
(code?: number, reason?: string) => void
Close this connection

Message Types

Messages can be strings or binary:

Connection Management

Getting Connections

Broadcasting

Send a message to all connected clients:

Connection Tags

Tag connections for easy filtering. Override getConnectionTags() to assign tags:

Per-Connection State

Store data specific to each connection using connection.state and connection.setState():
Connection state is:
  • Immutable - Read via connection.state, update via connection.setState()
  • Per-connection - Each connection has its own state
  • Persisted across hibernation - Survives agent sleep/wake cycles

The onStart Hook

onStart() is called once when the agent first starts, before any connections are established:

Protocol Message Control

By default, when a WebSocket client connects, the agent sends protocol text frames (CF_AGENT_IDENTITY, CF_AGENT_STATE, CF_AGENT_MCP_SERVERS) to keep the client in sync. You can suppress these on a per-connection basis by overriding shouldSendProtocolMessages:
When shouldSendProtocolMessages returns false for a connection:
  • No CF_AGENT_IDENTITY, CF_AGENT_STATE, or CF_AGENT_MCP_SERVERS frames are sent on connect
  • The connection is excluded from protocol broadcasts (state updates, MCP server changes)
  • Regular messages via connection.send() and this.broadcast() still work normally
This is useful for IoT devices, binary-only clients, or lightweight consumers that only need raw messages.

Checking Protocol Status

Use isConnectionProtocolEnabled to check whether a connection receives protocol messages:
This status persists across hibernation — a connection that was marked as no-protocol before hibernation remains no-protocol after waking up.

Error Handling

Handle errors gracefully with onError:

Hibernation

Agents support hibernation - they can sleep when inactive and wake when needed. This saves resources while maintaining WebSocket connections.

Enabling Hibernation

Hibernation is enabled by default. To disable:

How Hibernation Works

1

Agent is active

Handling connections
2

After ~10 seconds of no messages

Agent hibernates (sleeps)
3

WebSocket connections remain open

Handled by Cloudflare
4

When a message arrives

Agent wakes up
5

onMessage is called

As normal

What Persists Across Hibernation

Best Practice: Store important data in this.state or SQLite, not in class properties:

Common Patterns

Authentication on Connect

Validate users when they connect:

Chat Room with Broadcast

Presence Tracking

Track who’s online using per-connection state. This pattern is clean because connection state is automatically cleaned up when users disconnect:

API Reference

Agent Lifecycle Methods

(props?) => void | Promise<void>
Called once when agent starts
(request: Request) => Response | Promise<Response>
Handle HTTP requests
(connection, ctx) => void | Promise<void>
WebSocket connected
(connection, message) => void | Promise<void>
Message received
(connection, code, reason, wasClean) => void | Promise<void>
Connection closed
(connection, error) => void | Promise<void>
WebSocket error
(connection, ctx) => boolean
Control per-connection protocol frames (default: true)

Connection Management Methods

(tag?: string) => Iterable<Connection>
Get all connections, optionally by tag
(id: string) => Connection | undefined
Get connection by ID
(connection, ctx) => string[]
Override to tag connections
(message, without?: string[]) => void
Send to all connections
(connection) => boolean
Check if connection receives protocol messages