> ## 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.

# The Protocol

The socket server, the HTTP server and [`AgentClient`](/docs/agent-sdk/client-sdk) speak one protocol of JSON frames, encoded with SuperJSON so that a `Date`, a `Map`, a `Set` or `undefined` in a payload survives the wire. `@telnyx/edge-runtime/agent-socket` exports the frame functions and types for servers, and `@telnyx/edge-runtime/client` exports the same set for clients, with `isFrame` and `applyMergePatch` besides.

```ts theme={null}
import { encodeFrame, parseKnownFrame, type AnyKnownFrame } from "@telnyx/edge-runtime/agent-socket";
import { applyMergePatch, isFrame } from "@telnyx/edge-runtime/client";
```

## Versions

| Constant | Value | Meaning |
| - | - | - |
| `PROTOCOL_V1` | `1` | The v1 wire, the version the server and the client speak today. |
| `PROTOCOL_V2` | `2` | The v2 wire, the `attach`, `attached` and `event` vocabulary of attach-mode sessions. |
| `PROTOCOL_VERSION` | `1` | The version that is safe to stamp on the wire today. It stays equal to `PROTOCOL_V1` until both sides emit v2 frames, and v2 frames are stamped with `PROTOCOL_V2`. |

Every frame carries its version as `v` and its kind as `kind`.

## Functions

| Function | Exported From | Does |
| - | - | - |
| `encodeFrame(frame: AnyKnownFrame): string` | both | Encodes a frame of either version to a SuperJSON text frame. |
| `parseFrame(text: string): AnyFrame` | both | Parses a v1 text frame. Throws on malformed input. |
| `parseKnownFrame(text: string): AnyKnownFrame` | both | Parses a text frame of either version. Throws on malformed input. |
| `isKnownFrame(value: unknown): value is AnyKnownFrame` | both | `true` for a frame of either version. |
| `isFrame(value: unknown): value is AnyFrame` | `./client` | `true` for a frame of the shipped v1 protocol. |
| `applyMergePatch(target, patch): Record<string, unknown>` | `./client` | Applies an RFC 7396 merge patch to `target` and returns it: `null` deletes a key, objects merge recursively, and anything else replaces. It is the same function the server's `setState` uses. |

## v1 Frames

`AnyFrame` is the union of every v1 frame.

| `kind` | Sent By | Fields | Meaning |
| - | - | - | - |
| `call` | Client | `id`, `method`, `args?` | Invoke an `@rpc()` method. The answer is a `result` or an `error` with the same `id`. |
| `ping` | Client | None | A heartbeat, answered with `pong`. |
| `hello` | Server | None | Ends the bootstrap: the link is usable, and buffered calls flush. |
| `state` | Server | `snapshot?`, `patch?` | A `snapshot` replaces the client's state; a `patch` is a merge patch on top of it. A connect sends a snapshot, and each `setState` a patch. |
| `messages` | Server | `snapshot?`, `appended?` | The full message log on connect, then the newly appended messages. |
| `result` | Server | `id`, `value` | The return value of the `call` with that `id`. |
| `error` | Server | `id?`, `code`, `message` | With an `id`, that call rejects. Without one, the error is connection-level and the client rebuilds the link. |
| `pong` | Server | None | The answer to `ping`. |

`ErrorCode` is `"method_not_found"`, `"method_private"`, `"method_error"`, `"protocol_error"` or `"version_mismatch"`.

## v2 Frames

`AnyFrameV2` is the union of the attach-mode frames, `AnyKnownFrame` the union of both versions, and `FrameKindV2` the v2 `kind` values. Each v2 frame is exported as its own type.

| Type | `kind` | Sent By | Fields | Meaning |
| - | - | - | - | - |
| `AttachFrame` | `attach` | Client | `token?`, `subscribe?`, `cursors?` | Opens or reopens a session. The token is the credential, `subscribe` the [`Stream`](#streams-and-claims)s wanted, and `cursors` the per-stream positions to resume after, `{ events: 41 }` for example. |
| `AttachedFrame` | `attached` | Server | `grants`, `accepted` | The [`Claim`](#streams-and-claims)s the connection holds, and the accepted subset of the requested streams. |
| `EventFrame` | `event` | Server | `seq`, `type`, `payload`, `at` | One item of the agent's persistent [event log](/docs/agent-sdk/interface/events), in strict `seq` order. `seq` is also the resume cursor. |
| `ErrorFrameV2` | `error` | Server | `id?`, `code`, `message` | The v2 error, with an `ErrorCodeV2`. |

`ErrorCodeV2` is any `ErrorCode`, `"unauthorized"` or `"subscription_denied"`.

## Streams and Claims

`Stream` is `"state"`, `"messages"` or `"events"`, the streams a v2 client can subscribe to. `Claim` is `"read"`, `"rpc"` or any other string: a capability [`authorize`](/docs/agent-sdk/interface/authorize) grants a connection. With `authorize` configured, a `call` frame needs the `"rpc"` claim.
