# Browser Automation

Agents can read and search the web with the [Browserbase](https://www.browserbase.com) `browse` CLI. The page loads in a real browser in Browserbase's cloud and comes back as clean content — the VM never runs a browser.

## Setup

1. **Create a Browserbase account**

   [Sign up](https://www.browserbase.com/sign-up) and grab your API key and project id from the [dashboard](https://www.browserbase.com/settings):

   ```bash
   export BROWSERBASE_API_KEY=bb_...
   export BROWSERBASE_PROJECT_ID=...
   ```

2. **Install**

   ```bash
   npm install @rivet-dev/agentos @agentos-software/pi @agentos-software/browserbase
   ```

3. **Add `browse` to the VM**

   
examples/browserbase/server-minimal.ts:

```ts
import browserbase from "@agentos-software/browserbase";
import pi from "@agentos-software/pi";
import { agentOS, setup } from "@rivet-dev/agentos";

// `browse` is exposed inside the VM as a command on `$PATH`.
const vm = agentOS({
	software: [pi, browserbase],
});

export const registry = setup({ use: { vm } });
registry.start();
```

   
     Mount the [`browse` CLI skill](https://github.com/browserbase/stagehand/tree/main/packages/cli) into the agent's skills directory so it reaches for `browse` unprompted ([copy the skill folder from the example](https://github.com/rivet-dev/agentos/tree/main/examples/browserbase/skills)):

     

     
### Pi

     
examples/browserbase/server-skills-pi.ts:

```ts
import browserbase from "@agentos-software/browserbase";
import pi from "@agentos-software/pi";
import { agentOS, setup } from "@rivet-dev/agentos";

// Mount the local `skills/` folder into Pi's skills directory
// (`~/.pi/agent/skills`) so the agent can discover the `browse` CLI skill.
const skillsDir = new URL("./skills", import.meta.url).pathname;

const vm = agentOS({
	software: [pi, browserbase],
	mounts: [
		{
			path: "/home/agentos/.pi/agent/skills",
			plugin: { id: "host_dir", config: { hostPath: skillsDir } },
			readOnly: true,
		},
	],
});

export const registry = setup({ use: { vm } });
registry.start();
```

     

     
### Claude Code

     
examples/browserbase/server.ts:

```ts
import browserbase from "@agentos-software/browserbase";
import claude from "@agentos-software/claude-code";
import { agentOS, setup } from "@rivet-dev/agentos";

// Install the `browse` CLI alongside the Claude Code agent. Because `browse`
// reaches the web through the Browserbase cloud, no local browser or sandbox is
// needed — `browse` is exposed inside the VM as a command on `$PATH`.
//
// Mount the local `skills/` folder into Claude Code's skills directory
// (`~/.claude/skills`) so the agent discovers Browserbase's `browse` CLI skill
// and reaches for it on its own, without being told to in the prompt.
const skillsDir = new URL("./skills", import.meta.url).pathname;

const vm = agentOS({
	software: [claude, browserbase],
	mounts: [
		{
			path: "/home/agentos/.claude/skills",
			plugin: { id: "host_dir", config: { hostPath: skillsDir } },
			readOnly: true,
		},
	],
});

export const registry = setup({ use: { vm } });
registry.start();
```

     

     

   

4. **Use it**

   

   
### Agent uses browse

   
examples/browserbase/client-agent.ts:

```ts
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server-minimal";

const client = createClient<typeof registry>({
	endpoint: "http://localhost:6420",
});
const agent = client.vm.getOrCreate("my-agent");

// The Browserbase credentials go into the session environment, so every
// command the agent runs — including `browse` — inherits them.
await agent.sessions.open({
	agent: "pi",
	env: {
		BROWSERBASE_API_KEY: process.env.BROWSERBASE_API_KEY!,
		BROWSERBASE_PROJECT_ID: process.env.BROWSERBASE_PROJECT_ID!,
		ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY!,
	},
});

const response = await agent.sessions.prompt({
	content: [
		{
			type: "text",
			text: "Run `browse cloud fetch https://example.com` and tell me in one sentence what the page is about.",
		},
	],
});
console.log(response.message?.content ?? []);

await agent.sessions.delete();
```

   

   
### Drive browse directly

   
examples/browserbase/client-direct.ts:

```ts
import { createClient } from "@rivet-dev/agentos/client";
import type { registry } from "./server-minimal";

const client = createClient<typeof registry>({
	endpoint: "http://localhost:6420",
});
const agent = client.vm.getOrCreate("my-agent");

// Drive `browse` directly through the VM's process API. `browse cloud fetch`
// retrieves a page through the Browserbase cloud and returns it as JSON with the
// page rendered as markdown. `browse` reads its credentials from the command
// environment, which we pass through `exec`.
const env = {
	BROWSERBASE_API_KEY: process.env.BROWSERBASE_API_KEY!,
	BROWSERBASE_PROJECT_ID: process.env.BROWSERBASE_PROJECT_ID!,
};

const { stdout } = await agent.process.exec("browse cloud fetch https://example.com", {
	env,
});

const page = JSON.parse(stdout) as { statusCode: number; content: string };
console.log(`fetched status ${page.statusCode}`);
console.log(page.content);
```

   

   

## Command reference

```bash
browse cloud fetch https://example.com   # retrieve a page as markdown
browse cloud search "web scraping tools" # search the web
browse cloud sessions list               # list cloud browser sessions
browse cloud projects list               # list Browserbase projects
```

> **NOTE:** The [interactive driver mode](https://docs.browserbase.com/integrations/skills/browse-cli) (`browse open`, `browse click`, …) is not supported inside the VM yet ([#1631](https://github.com/rivet-dev/agentos/issues/1631)). For interactive automation, run `browse` inside an external sandbox via [External Sandboxes](/agentos/docs/sandboxes).
