Orchestration
Multiplayer
- Multiple clients connected to the same agent VM simultaneously
- Broadcast events so all subscribers see session output, process logs, and shell data
- Collaborative patterns where one user prompts and others observe
- Handoff between human and agent control
Multiple clients observing a session
Section titled “Multiple clients observing a session”All clients connected to the same actor receive broadcasted events. This enables building collaborative UIs where multiple users watch an agent work.
import { createClient } from "rivetkit/client";import type { registry } from "./server";
// Client A: creates the session and sends promptsconst clientA = createClient<typeof registry>("http://localhost:6420");const agentA = clientA.vm.getOrCreate(["shared-agent"]);
agentA.on("sessionEvent", (data) => { console.log("[A]", data.event.method);});
const session = await agentA.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },});await agentA.sendPrompt(session.sessionId, "Build a REST API");
// Client B: observes the same session (in a separate process)const clientB = createClient<typeof registry>("http://localhost:6420");const agentB = clientB.vm.getOrCreate(["shared-agent"]);
agentB.on("sessionEvent", (data) => { console.log("[B]", data.event.method);});
// Client B sees the same events as Client Aimport { agentOs } from "rivetkit/agent-os";import { setup } from "rivetkit";import common from "@rivet-dev/agent-os-common";import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({ options: { software: [common, pi] },});
export const registry = setup({ use: { vm } });registry.start();Shared process output
Section titled “Shared process output”All clients receive process output events from the same VM.
import { createClient } from "rivetkit/client";import type { registry } from "./server";
const client = createClient<typeof registry>("http://localhost:6420");const agent = client.vm.getOrCreate(["shared-agent"]);
// All connected clients see process outputagent.on("processOutput", (data) => { const text = new TextDecoder().decode(data.data); console.log(`[pid ${data.pid}] ${data.stream}: ${text}`);});
// All connected clients see shell dataagent.on("shellData", (data) => { const text = new TextDecoder().decode(data.data); process.stdout.write(text);});import { agentOs } from "rivetkit/agent-os";import { setup } from "rivetkit";import common from "@rivet-dev/agent-os-common";import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({ options: { software: [common, pi] },});
export const registry = setup({ use: { vm } });registry.start();Collaborative prompt/observe pattern
Section titled “Collaborative prompt/observe pattern”One client acts as the driver (sending prompts), while others observe.
import { agentOs } from "rivetkit/agent-os";import { setup } from "rivetkit";import common from "@rivet-dev/agent-os-common";import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({ onSessionEvent: async (c, sessionId, event) => { // Server-side hook runs once per event, even with multiple clients console.log("Session event:", sessionId, event.method); }, options: { software: [common, pi] },});
export const registry = setup({ use: { vm } });registry.start();import { createClient } from "rivetkit/client";import type { registry } from "./server";
// Driver clientconst driver = createClient<typeof registry>("http://localhost:6420");const driverAgent = driver.vm.getOrCreate(["shared-agent"]);
const session = await driverAgent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },});
// Observer client (different user, same actor)const observer = createClient<typeof registry>("http://localhost:6420");const observerAgent = observer.vm.getOrCreate(["shared-agent"]);
observerAgent.on("sessionEvent", (data) => { console.log("[observer]", data.event.method, data.event.params);});
// Driver sends a prompt. Observer sees the streaming response.await driverAgent.sendPrompt(session.sessionId, "Refactor the auth module");Reconnection with event replay
Section titled “Reconnection with event replay”When a client reconnects, use getSequencedEvents to replay missed events and catch up.
import { createClient } from "rivetkit/client";import type { registry } from "./server";
const client = createClient<typeof registry>("http://localhost:6420");const agent = client.vm.getOrCreate(["shared-agent"]);
// On reconnect, replay events from the last known sequence numberconst lastSeq = 42; // Track this on the client sideconst missedEvents = await agent.getSequencedEvents("session-id", { since: lastSeq,});for (const event of missedEvents) { console.log("Replaying:", event.sequenceNumber, event.notification.method);}
// Resume live streamingagent.on("sessionEvent", (data) => { console.log("Live:", data.event.method);});import { agentOs } from "rivetkit/agent-os";import { setup } from "rivetkit";import common from "@rivet-dev/agent-os-common";import pi from "@rivet-dev/agent-os-pi";
const vm = agentOs({ options: { software: [common, pi] },});
export const registry = setup({ use: { vm } });registry.start();Recommendations
Section titled “Recommendations”- Use the same actor key (e.g.
["shared-agent"]) for all clients that should share the same VM. - Events are broadcasted to all connected clients automatically. No additional setup needed.
- For reconnection, track the last sequence number on the client and use
getSequencedEventsto replay missed events. - Use the server-side
onSessionEventhook for logic that should run once per event regardless of connected clients.