Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 166 additions & 0 deletions box/guides/browser-use.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
---
title: "Scheduled Browser Use Agent"
---

Run a [Browser Use](https://browser-use.com) agent inside Upstash Box. The agent, the browser, and the files it writes all live in one box, and a schedule runs it again on a cron.

This guide builds an agent that reads Hacker News every morning and saves a report to the box.

---

## 1. Set up

- A **Box API key** from the [Upstash Console](https://console.upstash.com/box).
- An **Anthropic API key** from [API keys](https://platform.claude.com/settings/keys).

```bash
export UPSTASH_BOX_API_KEY=box_xxxxxxxxxxxxxxxxxxxxxxxx
export ANTHROPIC_API_KEY=sk-ant-api03-xxxxxxxxxxxx
```

```bash
pip install upstash-box
```

---

## 2. Write the agent

This file runs inside the box. It starts the box's Chromium, runs the task, and writes the result to `reports/`.

```python title="agent.py"
import asyncio
from datetime import datetime, timezone
from pathlib import Path

from browser_use import Agent, Browser, ChatAnthropic

TASK = """
Go to news.ycombinator.com and find the first 3 stories about AI on the front page.
Return a markdown list with the title, link, and points of each.
Open only the first one and add a two-sentence summary of it.
"""


async def main():
agent = Agent(
task=TASK,
llm=ChatAnthropic(model="claude-sonnet-4-5"),
browser=Browser(
executable_path="/usr/bin/chromium",
headless=True,
chromium_sandbox=False,
),
)
history = await agent.run(max_steps=15)
if not history.is_successful():
raise SystemExit("The agent did not finish the task")

name = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H%M")
report = Path("/workspace/home/reports") / f"{name}.md"
report.parent.mkdir(exist_ok=True)
report.write_text(history.final_result())


asyncio.run(main())
```

---

## 3. Set up the box

This script runs on your machine. It creates a box with a browser, installs Browser Use, runs the agent once, and schedules it.

```python title="setup.py"
import os

from upstash_box import Box

box = Box.create(
runtime="python",
browser=True,
env={"ANTHROPIC_API_KEY": os.environ["ANTHROPIC_API_KEY"]},
)
print(box.id)


def run(command):
result = box.exec.command(command)
if result.status != "completed":
raise RuntimeError(result.result)


# Install Browser Use and copy the agent in
run("pip install browser-use")
box.files.write(path="agent.py", content=open("agent.py").read())

# Run it once and print the report
run("python3 agent.py")
for file in box.files.list("reports"):
print(box.files.read(f"reports/{file.name}"))

# Run it every day at 08:00 UTC
box.schedule.exec(
cron="0 8 * * *",
command=["python3", "/workspace/home/agent.py"],
)
```

```bash
python setup.py
```

Example output after the box id. Stories and scores will vary:

```md
## Top 3 AI Stories from Hacker News

1. **AI companies leak data to advertisers [pdf]** - 179 points
- Link: https://jorgegarciaherrero.com/wp-content/interactivos/20260916-Prompt-like-a-butterfly-sting-like-a-tracker-(clean).pdf
- Summary: The paper analyzes privacy practices of conversational AI services, finding that 6 out of 9 web services and 3 out of 8 Android apps leak conversation data to third parties. This includes sensitive information such as URLs, titles, prompts, and screenshots being shared alongside persistent user identifiers.

2. **Jeeves. Reasoning improves Jev-like decision models** - 54 points
- Link: https://github.com/PostHog/jeeves

3. **Nvidia wants to put a watchdog chip next to every AI agent** - 197 points
- Link: https://www.cnbc.com/2026/09/28/nvidia-releases.html
```

The box pauses when idle. Each scheduled run wakes it, and the reports stay on the box.

<Note>
Run `setup.py` once. Each run creates a new box with its own daily schedule.
</Note>

---

## 4. Read the reports

Re-attach with the box id that `setup.py` printed:

```python title="reports.py"
from upstash_box import Box

box = Box.get("your-box-id")

for file in box.files.list("reports"):
print(box.files.read(f"reports/{file.name}"))
```

```bash
python reports.py
```

Delete the box when you no longer need it:

```python
box.delete()
```

---

## Next steps

- [Schedules](/box/overall/schedules) to pause a schedule or get a webhook when a run finishes.
- [Connect over CDP](/box/overall/browser/connect) to drive the box browser with Browser Use from your own machine.
- [Browser](/box/overall/browser/overview) for the SDK's own `observe`, `act`, and `extract`.
20 changes: 19 additions & 1 deletion box/overall/browser/connect.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: "Connect over CDP"
---

The box browser is a real Chromium, and you can drive it with the tools you already use. `cdpUrl()` returns an authenticated Chrome DevTools Protocol WebSocket URL that Playwright, Puppeteer, or Stagehand can connect to directly. There is no browser to install and nothing to manage.
The box browser is a real Chromium, and you can drive it with the tools you already use. `cdpUrl()` returns an authenticated Chrome DevTools Protocol WebSocket URL that Playwright, Puppeteer, Stagehand, or Browser Use can connect to directly. There is no browser to install and nothing to manage.

For a single no-LLM step without wiring up a CDP client, replaying an observed action with [`act(action)`](/box/overall/browser/ai-actions#replay-an-action-without-an-llm) is often enough. Reach for CDP when you want fully scripted, multi-step control.

Expand Down Expand Up @@ -76,6 +76,24 @@ await stagehand.init()
await stagehand.act("click the first link")
```

## Browser Use

[Browser Use](https://browser-use.com) can run its agent loop on the box browser:

```python agent.py
import asyncio
from browser_use import Agent, Browser, ChatAnthropic

agent = Agent(
task="Open upstash.com/docs/box/overall/quickstart and return the install command",
llm=ChatAnthropic(model="claude-sonnet-4-5"),
browser=Browser(cdp_url=cdp_url),
)

history = asyncio.run(agent.run())
print(history.final_result())
```

## Mixing CDP and SDK control

CDP clients and the SDK drive the same browser and the same tabs. A page opened by Playwright shows up in `box.browser.listTabs()`, and a tab created by the SDK is visible to Playwright. You can script the predictable steps like login and pagination with Playwright, hand the tab to [`act`](/box/overall/browser/ai-actions) for the steps that are easier to describe in natural language, and watch either through [Live View](/box/overall/browser/live-view).
Expand Down
2 changes: 1 addition & 1 deletion box/overall/browser/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ print(page.title)
</Card>

<Card title="Connect over CDP" href="/box/overall/browser/connect">
Drive the same browser with Playwright, Puppeteer, or Stagehand.
Drive the same browser with Playwright, Puppeteer, Stagehand, or Browser Use.
</Card>
</CardGroup>

Expand Down
1 change: 1 addition & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -2169,6 +2169,7 @@
"box/guides/code-review-agent",
"box/guides/langchain-deep-agents",
"box/guides/web-scraping-playwright",
"box/guides/browser-use",
"box/guides/ai-sdk-setup",
"box/guides/tanstack-setup",
"box/guides/eve-setup",
Expand Down
Loading