> ## Documentation Index
> Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# attach()

> **attach**(`ws`, `req?`): `Promise`\<`void`>

Attach a socket (call from the actor's `webSocket(ws, req)`). If `onConnect`
is configured it runs first as a gate: throw or `ctx.close()` rejects the
connection (closed, never admitted as a watcher, no `hello`/state). On
accept, sends the state snapshot then `hello`, and handles inbound
`call`/`ping` frames.

The returned Promise settles once the socket is wired and the `onConnect`
gate has run — NOT necessarily once the connection is admitted. With an
`authorize` hook the bootstrap needs the client's first frame, and the
Telnyx actor host delivers no frame until `webSocket()` has returned
(every frame is its own serialized turn, run after setup): so when no
frame has arrived yet, `attach` returns and the bootstrap runs later —
inside the first frame's own turn (an `attach` frame is authorized with
its token; anything else as anonymous), or on the `attachGraceMs` timer
for a client that sends nothing. Awaiting `attach` from `webSocket()` is
therefore safe and is the documented shape. Nothing after the
`await` is ordered against admission: observe authorized connections
through `onAttach` (which runs just before admission), not by reading
`watcherCount` or broadcasting right after `attach` resolves.

If the initial snapshot can't be read the connection is REJECTED (closed,
no `hello`) rather than admitted half-initialized — see `sendSnapshot`.

**Parameters**

| Parameter | Type |
| - | - |
| `ws` | [`AgentServerSocket`](/docs/agent-sdk/internals/socket/attach#agentserversocket) |
| `req?` | `Request` |

**Returns**

`Promise`\<`void`>

## The Actor Entry

The actor's [`webSocket(ws, req)`](/docs/edge-compute/stateful-actors/api-reference/base#websocket-ws-req) entry calls `attach()` once per accepted connection. [The Socket Server](/docs/agent-sdk/internals/the-socket-server#attaching-a-socket) shows the listeners it registers.

## AgentServerSocket

The `ws`-style socket surface the server drives, modeled structurally so
this module carries no `ws` dependency — anything with this shape works,
including the socket the platform hands an actor's `webSocket(ws, req)`.

**Properties**

**CLOSED**

> `readonly` **CLOSED**: `number`

The `readyState` value for a fully closed socket.

***

**OPEN**

> `readonly` **OPEN**: `number`

The `readyState` value for an open, writable socket.

***

**readyState**

> `readonly` **readyState**: `number`

The socket's current state, compared against `OPEN` / `CLOSED`.

**Methods**

**close()**

> **close**(`code?`, `reason?`): `void`

Close the socket with an optional close code and reason.

**Parameters**

| Parameter | Type |
| - | - |
| `code?` | `number` |
| `reason?` | `string` |

**Returns**

`void`

***

**on()**

**Call Signature**

> **on**(`event`, `listener`): `unknown`

Register a listener for inbound frames; it may return a promise a host can await.

**Parameters**

| Parameter | Type |
| - | - |
| `event` | `"message"` |
| `listener` | (`data`, `isBinary`) => `void` \| `Promise`\<`void`> |

**Returns**

`unknown`

**Call Signature**

> **on**(`event`, `listener`): `unknown`

Register a listener for the socket closing.

**Parameters**

| Parameter | Type |
| - | - |
| `event` | `"close"` |
| `listener` | (`code`, `reason`) => `void` |

**Returns**

`unknown`

**Call Signature**

> **on**(`event`, `listener`): `unknown`

Register a listener for socket errors.

**Parameters**

| Parameter | Type |
| - | - |
| `event` | `"error"` |
| `listener` | (`err`) => `void` |

**Returns**

`unknown`

***

**send()**

> **send**(`data`): `void`

Send one text frame.

**Parameters**

| Parameter | Type |
| - | - |
| `data` | `string` |

**Returns**

`void`
