Skip to main content
Call Actors

Connect

Open a persistent WebSocket connection to an actor. One connection carries action calls, event subscriptions, and errors as JSON messages, which is what handle.connect() does in the RivetKit client.

{actor} accepts the same forms as every gateway endpoint: an actor ID, {actor_id}@{token}, or an actor name with rvt-* query parameters. See Actor Routing.

Connection options travel as WebSocket subprotocols in the Sec-WebSocket-Protocol header because browsers cannot set arbitrary headers on an upgrade. Always include rivet, then add any of the prefixed entries below.

SubprotocolPurpose
rivetRequired. Lets servers that insist on a matching protocol accept the upgrade.
rivet_encoding.jsonMessage encoding. json is the default and is documented here. The RivetKit client uses cbor or bare; the payloads are the same, only the framing differs.
rivet_token.{token}Token to authenticate with. See WebSocket Requests.
rivet_conn_params.{params}Optional connection parameters passed to the actor’s createConnState and onBeforeConnect hooks, as URL-encoded JSON.
rivet_skip_ready_waitComplete the upgrade as soon as the actor is resolved instead of waiting for it to be ready.

Every message in both directions is a JSON object of the form { "body": { "tag": "<Message>", "val": { ... } } }. The server sends Init first; nothing else arrives before it. There is no ping or heartbeat message. Rely on WebSocket ping frames or your own timeout to detect a dead connection.

GET wss://api.rivet.dev/gateway/{actor}/connect

Handshake

After the upgrade completes, the server sends Init before any other message. Store connectionId if you need to correlate connection-scoped state; nothing else needs to be sent before calling actions or subscribing to events.

Init

Server to client. Initial connection message sent from server to client

FieldTypeRequiredDescription
actorIdstringYesID of the actor this connection is attached to.
connectionIdstringYesID of this connection. Matches c.conn.id inside the actor.
{
  "body": {
    "tag": "Init",
    "val": {
      "actorId": "00000000-0000-0000-0000-000000000000",
      "connectionId": "00000000-0000-0000-0000-000000000000"
    }
  }
}

Actions

Send an ActionRequest with a client-chosen id. The server answers with an ActionResponse carrying the same id, or with an Error whose actionId matches. Requests may be pipelined; responses are not guaranteed to arrive in order, so match on id rather than position.

This is the connection equivalent of Call Action over HTTP. Actions called on a connection can also read connection state set in createConnState.

ActionRequest

Client to server. Request to execute an action on the actor

FieldTypeRequiredDescription
idintegerYesClient-chosen identifier used to match the response. Any integer that is unique among in-flight requests on this connection.
namestringYesName of the action as defined in the actor’s actions map.
argsanyYesPositional arguments passed to the action, as a JSON array.
{
  "body": {
    "tag": "ActionRequest",
    "val": {
      "id": 1,
      "name": "increment",
      "args": [
        1
      ]
    }
  }
}

ActionResponse

Server to client. Response to an action request

FieldTypeRequiredDescription
idintegerYesThe id from the matching ActionRequest.
outputanyYesValue returned by the action. null if the action returned undefined.
{
  "body": {
    "tag": "ActionResponse",
    "val": {
      "id": 1,
      "output": 1
    }
  }
}

Events

Send a SubscriptionRequest with subscribe: true to start receiving Event messages for an event name, and subscribe: false to stop. Subscriptions are per connection and are lost when the connection closes, so resubscribe after reconnecting. The server does not acknowledge subscription changes. If the actor rejects a subscription, the connection is closed with the error as the close reason.

Events sent by the actor to a connection that has not subscribed to that event name are dropped.

SubscriptionRequest

Client to server. Request to subscribe or unsubscribe from an event

FieldTypeRequiredDescription
eventNamestringYesName of the event as defined in the actor’s events map.
subscribebooleanYestrue to subscribe, false to unsubscribe.
{
  "body": {
    "tag": "SubscriptionRequest",
    "val": {
      "eventName": "countChanged",
      "subscribe": true
    }
  }
}

Event

Server to client. Event broadcast to subscribed clients

FieldTypeRequiredDescription
namestringYesName of the event.
argsanyYesArguments passed to c.broadcast() or conn.send(), as a JSON array.
{
  "body": {
    "tag": "Event",
    "val": {
      "name": "countChanged",
      "args": [
        1
      ]
    }
  }
}

Errors

Errors on an established connection arrive as Error messages. actionId is set when the error answers a specific ActionRequest and null for connection-level errors such as a malformed message. The group and code values are the same ones the HTTP API returns; see Error Codes.

Errors that prevent the connection from being established, such as an invalid token or an actor that does not exist, are reported by closing the WebSocket with a reason of the form {group}.{code}#{ray_id}. See WebSockets.

Error

Server to client. Error message sent from server to client

FieldTypeRequiredDescription
groupstringYesSubsystem that produced the error, such as actor, auth, or user.
codestringYesError identifier within the group.
messagestringYesHuman-readable explanation. Do not match on it.
metadataanyNoStructured details attached by the actor or gateway, if any.
actionIdinteger | any | nullYesid of the ActionRequest this error answers, or null for connection-level errors.
actorobjectNoActor that handled the message, when known.
actor.actorIdstringYesID of the actor.
actor.generationnumber | integerYesGeneration of the actor process. Increments each time the actor restarts.
actor.keystringNoKey of the actor, if it has one.
{
  "body": {
    "tag": "Error",
    "val": {
      "group": "user",
      "code": "insufficient_funds",
      "message": "Balance is too low.",
      "metadata": {
        "balance": 5
      },
      "actionId": 1,
      "actor": {
        "actorId": "00000000-0000-0000-0000-000000000000",
        "generation": 1,
        "key": "my-counter"
      }
    }
  }
}