# Sessions > Source: `src/content/docs/agent-os/sessions.mdx` > Canonical URL: https://rivet.dev/docs/agent-os/sessions > Description: Create agent sessions, send prompts, stream responses, and replay event history. --- - **Create sessions** with any supported agent type - **Stream responses** in real time via `sessionEvent` subscriptions - **Replay events** with sequence numbers for reconnection and history - **Persist transcripts** automatically in SQLite across sleep/wake cycles - **Universal transcript format** using the Agent Communication Protocol (ACP) Currently only [Pi](https://github.com/mariozechner/pi-coding-agent) is supported as an agent. Amp, Claude Code, Codex, and OpenCode are coming soon. ## Create a session Use `createSession` to launch an agent inside the VM. Returns session metadata including capabilities and agent info. ```ts @nocheck client.ts import { createClient } from "rivetkit/client"; import type { registry } from "./server"; const client = createClient("http://localhost:6420"); const agent = client.vm.getOrCreate(["my-agent"]); const session = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, }); console.log(session.sessionId); console.log(session.capabilities); console.log(session.agentInfo); ``` ```ts @nocheck server.ts 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(); ``` ### `env` Environment variables to pass to the agent process. The VM does not inherit from the host `process.env`, so API keys must be passed explicitly. ```ts @nocheck const session = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, }); ``` ### `cwd` Working directory for the agent session inside the VM. Defaults to `/home/user`. ```ts @nocheck const session = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, cwd: "/home/user/project", }); ``` ### `mcpServers` Pass MCP servers to give the agent access to additional tools. MCP servers provide typed tool definitions that the agent's LLM can discover and call natively. #### Local MCP server Run an MCP server as a child process inside the VM. ```ts @nocheck const session = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, mcpServers: [ { type: "local", command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"], env: {}, }, ], }); ``` #### Remote MCP server Connect to an MCP server running outside the VM. ```ts @nocheck const session = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, mcpServers: [ { type: "remote", url: "https://mcp.example.com/sse", headers: { Authorization: "Bearer my-token", }, }, ], }); ``` ### `additionalInstructions` Append custom instructions to the agent's system prompt. ```ts @nocheck const session = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, additionalInstructions: "Always write tests before implementation.", }); ``` ### `skipOsInstructions` Skip the base OS instructions injection. Tool documentation is still included even when this is `true`. ```ts @nocheck const session = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, skipOsInstructions: true, }); ``` ## Send a prompt Use `sendPrompt` to send a message to an active session. The response contains the agent's reply. ```ts @nocheck client.ts import { createClient } from "rivetkit/client"; import type { registry } from "./server"; const client = createClient("http://localhost:6420"); const agent = client.vm.getOrCreate(["my-agent"]); const session = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, }); const response = await agent.sendPrompt( session.sessionId, "Create a TypeScript function that checks if a number is prime", ); console.log(response); ``` ```ts @nocheck server.ts 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(); ``` ## Stream responses Subscribe to `sessionEvent` to receive real-time streaming output from the agent. ```ts @nocheck client.ts import { createClient } from "rivetkit/client"; import type { registry } from "./server"; const client = createClient("http://localhost:6420"); const agent = client.vm.getOrCreate(["my-agent"]); // Subscribe to session events before sending the prompt agent.on("sessionEvent", (data) => { console.log(`[${data.sessionId}]`, data.event.method, data.event.params); }); const session = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, }); await agent.sendPrompt(session.sessionId, "Explain how async/await works"); ``` ```ts @nocheck server.ts 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(); ``` ## Cancel a prompt Use `cancelPrompt` to stop an in-progress prompt. ```ts @nocheck client.ts import { createClient } from "rivetkit/client"; import type { registry } from "./server"; const client = createClient("http://localhost:6420"); const agent = client.vm.getOrCreate(["my-agent"]); const session = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, }); // Start a long-running prompt const promptPromise = agent.sendPrompt( session.sessionId, "Refactor the entire codebase to use TypeScript strict mode", ); // Cancel after 10 seconds setTimeout(async () => { await agent.cancelPrompt(session.sessionId); }, 10_000); const response = await promptPromise; console.log(response); ``` ```ts @nocheck server.ts 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(); ``` ## Resume, close, and destroy sessions - `resumeSession` reconnects to a session that was suspended (e.g. after sleep) - `closeSession` gracefully closes a session - `destroySession` removes the session and all persisted data ```ts @nocheck client.ts import { createClient } from "rivetkit/client"; import type { registry } from "./server"; const client = createClient("http://localhost:6420"); const agent = client.vm.getOrCreate(["my-agent"]); // Resume a previously created session const resumed = await agent.resumeSession("session-id-from-earlier"); // Close without destroying persisted data await agent.closeSession(resumed.sessionId); // Destroy session and all persisted events await agent.destroySession(resumed.sessionId); ``` ```ts @nocheck server.ts 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(); ``` ## Runtime configuration Change model, mode, and thought level on a live session. ```ts @nocheck client.ts import { createClient } from "rivetkit/client"; import type { registry } from "./server"; const client = createClient("http://localhost:6420"); const agent = client.vm.getOrCreate(["my-agent"]); const session = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, }); // Change model await agent.setModel(session.sessionId, "claude-sonnet-4-6"); // Change mode (e.g. "plan", "auto") await agent.setMode(session.sessionId, "plan"); // Change thought level await agent.setThoughtLevel(session.sessionId, "high"); // Query available options const modes = await agent.getModes(session.sessionId); console.log(modes); const options = await agent.getConfigOptions(session.sessionId); console.log(options); ``` ```ts @nocheck server.ts 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(); ``` ## Replay events Use `getSequencedEvents` to replay in-memory session events (for live reconnection while the VM is running), or `getSessionEvents` to replay from persisted storage (for transcript history, including when the VM is not running). See [Events](/docs/agent-os/events#event-replay) for details on the difference. ```ts @nocheck client.ts import { createClient } from "rivetkit/client"; import type { registry } from "./server"; const client = createClient("http://localhost:6420"); const agent = client.vm.getOrCreate(["my-agent"]); const session = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, }); await agent.sendPrompt(session.sessionId, "Hello"); // Get all events const events = await agent.getEvents(session.sessionId); console.log(events); // Get events with sequence numbers (for pagination/reconnection) const sequenced = await agent.getSequencedEvents(session.sessionId, { since: 0, }); console.log(sequenced); ``` ```ts @nocheck server.ts 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(); ``` ## Persisted session history Query session history from SQLite. Works even when the VM is not running. ```ts @nocheck client.ts import { createClient } from "rivetkit/client"; import type { registry } from "./server"; const client = createClient("http://localhost:6420"); const agent = client.vm.getOrCreate(["my-agent"]); // List all persisted sessions const sessions = await agent.listPersistedSessions(); for (const s of sessions) { console.log(s.sessionId, s.agentType, s.createdAt); } // Get full event history for a session const events = await agent.getSessionEvents(sessions[0].sessionId); for (const e of events) { console.log(e.seq, e.event.method, e.createdAt); } ``` ```ts @nocheck server.ts 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(); ``` ## Multiple sessions A single VM can run multiple sessions simultaneously. Each session has its own agent process but shares the same filesystem. Use different session IDs to manage them independently. ```ts @nocheck client.ts import { createClient } from "rivetkit/client"; import type { registry } from "./server"; const client = createClient("http://localhost:6420"); const agent = client.vm.getOrCreate(["my-agent"]); // Create two sessions in the same VM const coder = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, }); const reviewer = await agent.createSession("pi", { env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! }, }); // Coder writes code await agent.sendPrompt(coder.sessionId, "Write a REST API at /home/user/api.ts"); // Reviewer reads and reviews the same file await agent.sendPrompt(reviewer.sessionId, "Review /home/user/api.ts for issues"); // Close each session independently await agent.closeSession(coder.sessionId); await agent.closeSession(reviewer.sessionId); ``` ```ts @nocheck server.ts 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 - Subscribe to `sessionEvent` **before** calling `sendPrompt` to avoid missing early events. - Use `getSequencedEvents` with `since` for reconnection. Track the last sequence number you processed. - Use `listPersistedSessions` and `getSessionEvents` to build transcript history UIs without requiring a running VM. - Call `closeSession` when done to release resources. Use `destroySession` only when you want to permanently delete session data. _Source doc path: /docs/agent-os/sessions_