constructor
new Agent<Called by the runtime on every activation — never construct an agent yourself. Re-arms the task scheduler to the earliest pending task (insideE,State>(ctx,env,options?):Agent<E,State>
ctx.blockConcurrencyWhile), so persistent timers resume after a crash or
restart. A subclass constructor must call super(ctx, env) first.
options is where a subclass configures the pieces the folded surface
builds on its behalf — event retention and the connection engine’s attach
window (see AgentOptions). Declare a constructor and forward a
literal to super; the runtime keeps calling your class with (ctx, env)
and the values are read here, once, and never re-read.
Returns
Agent<E, State>
Overrides
StatefulActor<E>.constructor
AgentOptions
Construction-time configuration for an agent’s persistent event log and its built-in connection engine. The folded connection surface builds both for you, which leaves nothing to configure at the call site — so an agent that needs different retention or a different attach window declares a constructor and forwards anAgentOptions literal to super:
How long (ms) the connection engine waits for a client’s first frame before admitting the connection as an anonymous reader. Clients that never attach send nothing until the bootstrap completes, so this is the latency such a client pays on connect — and, on a policy that rejects anonymous connections, the window a slow client must attach within. Omitted, the engine uses its own default (300).optionalattachGraceMs?:number
events?
Retention foroptionalevents?:EventLogOptions
this.events, the agent’s persistent progress-event stream —
see EventLogOptions. Omitted, the log keeps its default 1000 rows.
ctx
The actor’s identity + storage + concurrency primitives. Inherited fromprotectedreadonlyctx:ActorContext
StatefulActor.ctx
env
The bindings environment for this actor’s worker scope. Inherited fromprotectedreadonlyenv:E
StatefulActor.env
fetch()
fetch(Optional HTTP-style entry._req):Promise<Response>
stub.fetch(req) from a caller routes here.
Subclasses override; the base default returns 404.
Request and Response are the standard Fetch API globals (Node 18+
exposes both natively).
Parameters
Returns
Promise<Response>
Inherited from
StatefulActor.fetch
webSocket()
webSocket(Default connection surface: once opted in, every socket handed to the agent speaks the agent socket protocol with zero subclass code. The surface is opt-in: it activates only when the subclass overrides a connection seam (ws,req):void|Promise<void>
authorize or
onAttach) or webSocket itself. Overriding
onConnect alone does NOT activate it — that
hook predates the surface, so a subclass already using it stays
socketless. An agent that never opted in never asked to hold sockets —
this method then throws AgentSocketsNotEnabledError before
touching the socket, and the runtime rejects the connection exactly as
it does for an actor with no webSocket handler: nothing is sent,
nothing is held.
Once opted in, the default implementation admits the socket: clients
receive a state snapshot on connect (plus message history, and event
replay when subscribed), then live pushes of every committed
setState / this.messages append /
this.events emit — and, once granted the "rpc" claim by an
authorize override, can invoke
@rpc()-decorated methods remotely. Connections pass
through authorize and
onAttach on the way in.
Override it to take ownership of raw sockets: a socket you handle
WITHOUT calling super.webSocket(ws, req) never touches the protocol
layer — no frames are sent to it and it is not counted in
attachments. Route the sockets you do want
on the protocol through super.webSocket(ws, req).
Parameters
Returns
void | Promise<void>
Overrides
StatefulActor.webSocket
onConnect()
Hook: a client connection is established. Override to authorize, seed, or close the connection. The default implementation does nothing. When the connection surface is active (anprotectedonConnect(_conn):Promise<void>
authorize / onAttach /
webSocket override) and this hook is overridden, the default
webSocket runs it once per new connection —
before authorization or any snapshot — with a context carrying the
upgrade request (req) and a close to reject the connection. Frames a
fast client sends while this gate is pending are buffered and replayed
in order once the connection is admitted. Overriding this hook alone
does NOT activate the connection surface. For claims-based decisions
prefer authorize and
onAttach, which run with the connection’s
resolved claims.
Parameters
Returns
Promise<void>
alarm()
alarm(Reserved: the SDK claims the actor’s alarm slot to drive the task scheduler. When the alarm fires, this drains every due task, dispatches each to the method it names (or_info):Promise<void>
onTask), and re-arms the
alarm to the next deadline. Do not override alarm() in an Agent
subclass — doing so breaks queue / schedule / every. If you need
timed work, schedule a task instead.
Parameters
Returns
Promise<void>
Overrides
StatefulActor.alarm
destroy()
Erase everything this agent has accumulated, in one call. For when the thing the agent represents is over — a phone number is released, an account closes, a case is settled — and what comes next must inherit nothing. Rather than hand-deleting each piece and hoping none was missed,protecteddestroy():Promise<void>
destroy() empties them together:
- State —
getStatereads backinitialState()again. - Timers — every pending
queue/schedule/everytask is removed,listSchedulesis empty, and the agent’s wake-up is cancelled. A 24-hour follow-up booked before the number changed hands never fires. - Conversation history —
this.messagesis emptied, seq counter included, so the next message isseq1. - Progress events —
this.eventslikewise. - Connections — every client the agent is holding is closed, and
attachmentsdrops to zero.
destroy() empties an agent; it does not remove it. The instance keeps
existing and stays usable: the very next call writes into a clean agent,
exactly as the first call to a brand-new one does. Removing the instance
itself is a separate, platform-level operation.
Two things are deliberately left alone, because the agent does not own
them:
- Objects in a bucket. Content offloaded through a
BlobStorelives in object storage under keys of your choosing, and may be large, shared between agents, or subject to your own retention rules. Delete what you no longer want through the bucket, before calling this. - Keys you wrote yourself. Anything the subclass put in
ctx.storagedirectly is yours to manage; only the agent’s own stores are emptied.
@rpc()-decorated method, a fetch
route, a task that fires when a retention window closes):
destroy must rename it (or align it to override this method).
Returns
Promise<void>