Skip to main content
The runtime constructs and activates agent instances for you; these are the members involved in that lifecycle — construction, the inherited actor primitives, the inbound HTTP/WebSocket entry points, and the alarm slot the SDK reserves for the task scheduler.

constructor

new Agent<E, State>(ctx, env, options?): Agent<E, State>
Called by the runtime on every activation — never construct an agent yourself. Re-arms the task scheduler to the earliest pending task (inside 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.
Parameters 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 an AgentOptions literal to super:
The values are read once, during construction, and never re-read — the object you pass is not retained. Properties attachGraceMs?
optional attachGraceMs?: number
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).
events?
optional events?: EventLogOptions
Retention for this.events, the agent’s persistent progress-event stream — see EventLogOptions. Omitted, the log keeps its default 1000 rows.

ctx

protected readonly ctx: ActorContext
The actor’s identity + storage + concurrency primitives. Inherited from StatefulActor.ctx

env

protected readonly env: E
The bindings environment for this actor’s worker scope. Inherited from StatefulActor.env

fetch()

fetch(_req): Promise<Response>
Optional HTTP-style entry. 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(ws, req): void | Promise<void>
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 (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()

protected onConnect(_conn): Promise<void>
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 (an 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(_info): Promise<void>
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 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()

protected destroy(): Promise<void>
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, destroy() empties them together:
  • StategetState reads back initialState() again.
  • Timers — every pending queue / schedule / every task is removed, listSchedules is empty, and the agent’s wake-up is cancelled. A 24-hour follow-up booked before the number changed hands never fires.
  • Conversation historythis.messages is emptied, seq counter included, so the next message is seq 1.
  • Progress eventsthis.events likewise.
  • Connections — every client the agent is holding is closed, and attachments drops to zero.
The erasure is persistent, not just in-memory: an agent that is destroyed and later activated again — a stray inbound message routed to the same name — comes up as a fresh agent, with nothing left to fire, replay, or read. 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 BlobStore lives 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.storage directly is yours to manage; only the agent’s own stores are emptied.
Safe to call on an agent that has never been used, and safe to call twice: emptying what is already empty succeeds and changes nothing. Nothing calls this for you — expose it however your application decides an agent is finished (an @rpc()-decorated method, a fetch route, a task that fires when a retention window closes):
Added with SDK 0.15 — a new inherited member, so a subclass that already declares destroy must rename it (or align it to override this method). Returns Promise<void>