---
title: "Events"
description: "Full event catalog with payload shapes for agentOS."
skill: true
---

## Event types

### sessionEvent

Emitted for every agent session event (streaming output, errors, status changes).

```ts @nocheck
agent.on("sessionEvent", (data) => {
  // data.sessionId: string
  // data.event: JsonRpcNotification (method, params)
  console.log(data.sessionId, data.event.method, data.event.params);
});
```

Events are also persisted to SQLite for replay via `getSessionEvents`.

### permissionRequest

Emitted when an agent requests permission to use a tool.

```ts @nocheck
agent.on("permissionRequest", async (data) => {
  // data.sessionId: string
  // data.request: PermissionRequest (id, toolName, etc.)
  console.log("Permission requested:", data.request);

  await agent.respondPermission(data.sessionId, data.request.permissionId, "once");
});
```

See [Permissions](/docs/agent-os/permissions) for approval patterns.

### processOutput

Emitted when a spawned process writes to stdout or stderr.

```ts @nocheck
agent.on("processOutput", (data) => {
  // data.pid: number
  // data.stream: "stdout" | "stderr"
  // data.data: Uint8Array
  const text = new TextDecoder().decode(data.data);
  console.log(`[${data.pid}] ${data.stream}: ${text}`);
});
```

### processExit

Emitted when a spawned process exits.

```ts @nocheck
agent.on("processExit", (data) => {
  // data.pid: number
  // data.exitCode: number
  console.log(`Process ${data.pid} exited with code ${data.exitCode}`);
});
```

### shellData

Emitted when an interactive shell produces output.

```ts @nocheck
agent.on("shellData", (data) => {
  // data.shellId: string
  // data.data: Uint8Array
  const text = new TextDecoder().decode(data.data);
  process.stdout.write(text);
});
```

### cronEvent

Emitted when a cron job runs.

```ts @nocheck
agent.on("cronEvent", (data) => {
  // data.event: CronEvent
  console.log("Cron event:", data.event);
});
```

### vmBooted

Emitted when the VM finishes booting. No payload.

```ts @nocheck
agent.on("vmBooted", () => {
  console.log("VM is ready");
});
```

### vmShutdown

Emitted when the VM is shutting down.

```ts @nocheck
agent.on("vmShutdown", (data) => {
  // data.reason: "sleep" | "destroy" | "error"
  console.log("VM shutting down:", data.reason);
});
```

## Client subscription pattern

Subscribe to events before triggering actions to avoid missing early events.

<CodeGroup>
```ts @nocheck client.ts
import { createClient } from "rivetkit/client";
import type { registry } from "./server";

const client = createClient<typeof registry>("http://localhost:6420");
const agent = client.vm.getOrCreate(["my-agent"]);

// Subscribe to all relevant events first
agent.on("sessionEvent", (data) => {
  console.log("Session:", data.event.method);
});
agent.on("processOutput", (data) => {
  console.log("Process:", new TextDecoder().decode(data.data));
});
agent.on("processExit", (data) => {
  console.log("Exit:", data.pid, data.exitCode);
});

// Then trigger actions
const session = await agent.createSession("pi", {
  env: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY! },
});
await agent.sendPrompt(session.sessionId, "Run the test suite");
```

```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();
```
</CodeGroup>

## Event replay

There are two ways to replay session events:

- **`getSequencedEvents`** returns events from the in-memory session. Each event has a `sequenceNumber` and a `notification` (the raw JSON-RPC notification). Use this for live reconnection while the VM is running.
- **`getSessionEvents`** returns events from persisted storage (SQLite). Each event has a `seq`, `event`, and `createdAt`. Use this for transcript history, including when the VM is not running.

<CodeGroup>
```ts @nocheck client.ts
import { createClient } from "rivetkit/client";
import type { registry } from "./server";

const client = createClient<typeof registry>("http://localhost:6420");
const agent = client.vm.getOrCreate(["my-agent"]);

// Replay events from sequence 0
const events = await agent.getSequencedEvents("session-id", { since: 0 });
for (const e of events) {
  console.log(e.sequenceNumber, e.notification.method);
}

// Replay from persisted storage (works without running VM)
const persisted = await agent.getSessionEvents("session-id");
for (const e of persisted) {
  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();
```
</CodeGroup>
