Skip to content
GitHub Get Started
Agent

Sessions

Sessions launch an agent inside the VM, stream its responses in real time over sessionEvent, and persist a replayable ACP transcript that survives sleep/wake.

Use createSession to launch an agent inside the VM. Returns session metadata including capabilities and agent info. The agent starts in /home/agentos by default; override it with the cwd option below.

client.ts
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "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);

See Full Example

The second argument to createSession accepts:

  • env: environment variables for the agent process (e.g. API keys). Not inherited from the host.
  • cwd: working directory inside the VM. Defaults to /home/agentos.
  • mcpServers: MCP servers (local child processes or remote URLs) exposing extra tools.
  • additionalInstructions: text appended to the agent’s system prompt.
  • skipOsInstructions: skip the base OS instructions injection. Tool documentation is still included.

Use sendPrompt to send a message to an active session. The response contains the agent’s reply.

client.ts
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "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.text);

See Full Example

Subscribe to sessionEvent to receive real-time streaming output from the agent.

client.ts
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "http://localhost:6420" });
const agent = client.vm.getOrCreate("my-agent");
const conn = agent.connect();
// Subscribe to session events before sending the prompt
conn.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");

See Full Example

Use cancelPrompt to stop an in-progress prompt.

client.ts
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "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.text);

See Full Example

  • closeSession gracefully closes a session without removing persisted data
  • destroySession removes the session and all persisted data
  • To reconnect to a previously created session and replay its history, see Replay events and Resuming a suspended session
client.ts
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "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! },
});
// Close without destroying persisted data
await agent.closeSession(session.sessionId);
// Destroy session and all persisted events
await agent.destroySession(session.sessionId);

See Full Example

Change model, mode, and thought level on a live session.

client.ts
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "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);

See Full Example

Use getSessionEvents to replay a session’s persisted events, including for VMs that are not currently running. Pair it with listPersistedSessions to find earlier sessions.

client.ts
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "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");
// Replay persisted events
const events = await agent.getSessionEvents(session.sessionId);
console.log(events);

See Full Example

Query session history from SQLite. Works even when the VM is not running.

client.ts
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "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);
}

See Full Example

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.

client.ts
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server";
const client = createClient<typeof registry>({ endpoint: "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/agentos/api.ts");
// Reviewer reads and reviews the same file
await agent.sendPrompt(reviewer.sessionId, "Review /home/agentos/api.ts for issues");
// Close each session independently
await agent.closeSession(coder.sessionId);
await agent.closeSession(reviewer.sessionId);

See Full Example

The agent (ACP adapter) runs as a process inside the VM. It uses stdout for ACP protocol traffic, so its stderr is the channel for logs, warnings, and crash diagnostics. Pass onAgentStderr to the VM to capture it, and route it to your own logger to see exactly what the agent is doing (or why it exited).

server.ts
import { agentOS, setup } from "@rivet-dev/agentos";
import pi from "@agentos-software/pi";
const vm = agentOS({
software: [pi],
onAgentStderr(event) {
// event: { sessionId, agentType, processId, pid, chunk: Uint8Array }
const line = new TextDecoder().decode(event.chunk);
logger.info(`[agent:${event.agentType} session:${event.sessionId}] ${line}`);
},
});
export const registry = setup({ use: { vm } });
registry.start();