Skip to main content
Clients

Client SDK

Call an agent from your backend, scripts, or any JavaScript runtime, and stream its events.

The client is the rivetkit/client package. It calls actions on the agent and gets the agent’s events over a connection. A browser connects with a short-lived token from your backend.

client.tsyour backendBrowserbrowser.tstoken.tsissueTokenAgent Actoractionseventsfetch tokenconnect with token

Handles and connections

  • With no options, createClient() reads RIVET_ENDPOINT, RIVET_NAMESPACE, and RIVET_TOKEN from the environment, and defaults to a local Rivet at localhost:6420.
  • The getOrCreate method returns a handle to the agent with that key, and creates the agent on first use. Actions called on the handle, like conversation.context, are single requests.
  • An agent starts with one root conversation. The harness.root() action returns its id, and prompt uses it unless you pass a conversationId.
  • Calling connect() opens a live connection that can receive events. Actions called before it opens wait until it does.
  • A dropped connection reconnects on its own. The onStatusChange callback reports connecting, connected, and disconnected, and idle after dispose() closes the connection for good.

Events

Events go only to a connection that asks for them. Call conversation.watchEvents(id) on the connection. It returns a snapshot of the conversation, including any answer in progress, and then the connection receives pi.events with { conversationId, seq, events } as the agent works.

  • Events from before the call are not sent again. Read them from the snapshot.
  • A short answer can arrive whole in message_end, with no text_delta before it, so print the rest of the text there.
  • The seq number goes up by one for each batch. If a number is missing, call watchEvents again to get a new snapshot.
  • To stop listening, call the function that on returns, or conversation.unwatchEvents(id).

See Session Lifecycle for the event types.

Results and errors

  • The prompt action resolves when the run ends. The result is { status: "done", text } with the answer, or { status: "unanswered", reason }.
  • A model error doesn’t reject. The status is "unanswered", and reason explains why.
  • Pass a requestId to make retries safe. A second prompt with the same requestId returns the first one’s result and doesn’t run the agent again.
  • While a run is in progress, a new prompt waits as a follow-up. Pass whenBusy: "steer" to send it into the current run, or "reject" to make prompt reject with the ConversationBusy code.
  • The prompt action rejects with an ActorError when the action itself fails. For example, the run passes the ten-minute action timeout (action_timed_out). A timeout only stops the wait. The run keeps going until it finishes or conversation.abort(id) stops it.
  • To start a run without waiting for it, call conversation.submit(id, { type: "input", content }). Follow its progress with events.

Browsers

A browser shouldn’t hold your Rivet credentials. Your backend checks who the user is, then mints a short-lived token that reaches only their agent.

  • In token.ts, your backend resolves the user’s agent and calls issueToken, which returns a token for that one agent that expires in 15 minutes.
  • In browser.ts, the client connects with getForId, and getToken fetches a new token whenever the old one expires, so the connection stays up.

See JWTs and Authentication.

The same actions work over HTTP. See the curl tab in the Quickstart.

See the client documentation in the Actors docs for everything rivetkit/client can do.