How I Gave My AI Agents a Real Browser — and Killed My X API Bill

The Problem

Xavier, my crypto research agent, was burning $4–5 a day on X API calls. Watchlist scans, thread reads, keyword searches — all through the paid API at $0.005 per tweet. That's $150/mo just so one agent can read tweets.

I run 5 specialized agents through OpenClaw on Telegram — Junior (orchestrator), Jesse/Trader (market data), Xavier (research), Builder, and Food. They all live on the same EC2 instance, all powered by Claude. Xavier was the expensive one.

The whole time, the answer was staring at me. Chrome can read X for free. I just needed to make it work for agents.

The Server

Everything runs on a single EC2 instance in Ohio. 2 vCPUs, 8GB RAM, 30GB storage, Ubuntu 24.04. Costs about $60/mo on-demand (less if reserved). That one box runs:

OpenClaw — the gateway that connects all 5 agents to Telegram, handles crons, routes tasks.

The Memory Stack — mcp-memory for structured facts, memsearch for passive markdown indexing, the whole system from my last article.

Mission Control — my dashboard at dashboard.dogwiz.xyz.

Cloudflare Tunnel — exposes brain.dogwiz.xyz publicly so I can search memory from anywhere.

And now, the new piece:

What I Actually Built

A persistent Chrome browser that runs 24/7 on the server, logged into X as @Dogwiz, that any agent can control.

The fake screen. Chrome needs a display to render pages. Xvfb fakes a 1920x1080 monitor. Chrome doesn't know the difference. Both run as system services — they survive reboots and restart automatically if they crash.

The browser. Chromium, running headless, exposing Chrome DevTools Protocol (CDP) on a local port. CDP is the key — it lets you control the browser programmatically over a websocket. Navigate, read pages, click things, inject cookies.

Cookie login. Instead of logging in through a form (which would need 2FA and break every time), I inject my X session cookies directly through CDP. Two cookies, three websocket calls, two seconds. Browser reloads and it's logged into my account.

The OpenClaw connection. One config change: attachOnly: true. This tells OpenClaw "don't spawn your own Chrome — use the one already running." Now every agent shares the same authenticated browser session. No conflicts, no extra resources.

How Xavier Uses It

Xavier's research skill now has a --browser flag. Flip it on and searches, profile reads, watchlist scans, and tweet fetches all go through the real browser instead of the paid API.

The fallback chain is clean: try the browser first. If cookies are expired, fall back to bird CLI (a free tool that uses the same session cookies). If that fails too, then hit the paid API as a last resort.

In practice? Xavier hasn't touched the paid API in days.

The Real Unlock: Claude Code Agents

Here's the part I didn't expect.

Before the persistent browser, OpenClaw couldn't spawn Claude Code as a background agent. Every time it tried, the browser tool would launch its own Chrome, hit resource limits on the box, and crash. Multi-file builds, deep code work — none of it could happen from a Telegram message.

With one persistent Chrome handling all browser needs and attachOnly preventing new ones from spawning, that bottleneck just disappeared.

Now Xavier can decide "this needs a multi-file build," write a task spec, and spawn an Opus-powered Claude Code agent in the background. The agent reads existing code, builds new files, wires everything together, tests it, and reports back to Telegram when it's done.

The moment it clicked: Xavier analyzed its own X research skill, decided it could replace the paid API path with a browser-based scraper, spawned a Claude Code agent called faint-glade to build it, and let it cook. All from Telegram. All autonomous.

That's not a chatbot doing a task. That's an agent building its own tools.

What's Live Now

Persistent Chrome running 24/7, logged into X, wired to OpenClaw. Xavier doing all research through the browser — zero API cost. Claude Code agents spawnable as background tasks from Telegram. A three-tier fallback (browser → bird CLI → paid API) so nothing breaks if cookies expire.

When they do expire, I just say "re-inject X cookies" and it's fixed in two seconds. Could automate that with a cron. Probably will next week.

Why This Matters

The browser was always right there. Chrome can read anything you can read. The trick was making it persistent, authenticated, and available to agents through a clean protocol.

Two system services and a 15-line Python script turned a $150/mo API bill into $0.

Built on top of:

→ OpenClaw — the open-source AI agent framework: github.com/openclaw/openclaw

→ Claude by Anthropic — powers all 5 agents + Claude Code background agents

→ Chrome DevTools Protocol (CDP) — the websocket protocol that makes browser control possible

→ My memory stack from the last article: agent-memory-stack

Running on: AWS EC2 (t3.large, us-east-2), Ubuntu 24.04, Cloudflare Tunnel