Skip to content
Open
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Kernel paired with the rest of your stack.
| [mastra-web-task-assistant](integrations/mastra-web-task-assistant/) | Human-in-the-loop web task assistant with memory, built on Mastra |
| [vibium](integrations/vibium/) | Vibium browser automation over WebDriver BiDi |
| [tinker-rl](integrations/tinker-rl/) | RL training for computer use agents, using Tinker |
| [fx-colocated-agent](integrations/fx-colocated-agent/) | Running Vercel's fx agent inside a Kernel browser VM, co-located with the browser it drives |

## Useful resources

Expand Down
35 changes: 35 additions & 0 deletions integrations/fx-colocated-agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# fx, co-located with its browser

Runs [fx](https://fx.sh), Vercel Labs' terminal-first coding agent, *inside* the same Kernel browser VM as the Chromium instance it drives — instead of connecting to the browser remotely over Kernel's public API or MCP server.

Normally an agent drives a Kernel browser from outside the VM: each tool call is a network round trip to Kernel's API, which then talks to the browser. This recipe uploads the fx binary directly into the VM (via [process execution](https://www.kernel.sh/docs/browsers/process-execution)) and points it at the VM's local `kernel-images` playwright daemon on `127.0.0.1:10001`. Every tool call becomes a loopback request instead of a hop through Kernel's control plane, which matters for latency-sensitive or high-tool-call-volume agent loops.

## How it works

1. `kernel browsers create` starts a browser session.
2. `kernel browsers fs upload` copies the fx binary into the VM, and `kernel browsers process exec` marks it executable.
3. A small wrapper script (`run_fx.sh`) is uploaded the same way. It sets a system prompt telling fx to drive the browser by POSTing Playwright code to the in-VM playwright daemon, then calls `fx ask`.
4. `kernel browsers process exec` runs the wrapper synchronously inside the VM, with `AI_GATEWAY_API_KEY` and `FX_MODEL` passed through as process environment variables.
5. `kernel browsers delete` tears down the session.

## Prerequisites

- [Kernel CLI](https://www.kernel.sh/docs/reference/cli), authenticated (`KERNEL_API_KEY` set or `kernel login` run).
- `jq`, to parse the session ID out of `kernel browsers create`'s JSON output.
- An [AI Gateway](https://vercel.com/docs/ai-gateway) API key (`AI_GATEWAY_API_KEY`), which fx uses to reach the model.

## Run it

```bash
export KERNEL_API_KEY="your-kernel-api-key"
export AI_GATEWAY_API_KEY="your-ai-gateway-api-key"
./run.sh
```

The script prints fx's JSON result, which includes the top 5 Hacker News article titles fx retrieved by driving the co-located browser.

## Related

- [Process execution](https://www.kernel.sh/docs/browsers/process-execution) — running commands inside a browser VM.
- [File I/O](https://www.kernel.sh/docs/browsers/file-io) — uploading and downloading files from a browser VM.
- [fx integration guide](https://www.kernel.sh/docs/integrations/vercel/fx) — the standard (non-co-located) way to give fx a Kernel browser over MCP.
44 changes: 44 additions & 0 deletions integrations/fx-colocated-agent/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/sh
# Runs the fx coding agent (https://fx.sh) inside a Kernel browser VM, co-located
# with the browser it controls, so each tool call is a loopback instead of a
# round trip through Kernel's public API.
#
# Requires: kernel CLI authenticated (KERNEL_API_KEY), AI_GATEWAY_API_KEY.
set -e

SESSION_ID=$(kernel browsers create -t 900 -y -o json | jq -r .session_id)

# Upload fx into the VM.
curl -fsSL https://releases.fx.sh/latest.txt -o /tmp/fx_version.txt
VERSION=$(cat /tmp/fx_version.txt)
curl -fsSL "https://releases.fx.sh/${VERSION}/fx-linux-x86_64.tar.gz" | tar -xz -C /tmp fx
kernel browsers fs upload "$SESSION_ID" --file /tmp/fx:/usr/local/bin/fx
kernel browsers process exec "$SESSION_ID" --command chmod --args +x --args /usr/local/bin/fx

# fx reaches the browser via the in-VM kernel-images API's playwright-daemon
# on 127.0.0.1:10001.
cat > /tmp/run_fx.sh <<'EOF'
#!/bin/sh
set -e
SYSTEM_PROMPT="You control a live Chromium browser running on this same \
machine (co-located, no network hop). To drive it, write a JSON payload file \
containing {\"code\": \"<playwright TypeScript>\"} where the code has page, \
context, and browser bound, then POST it: curl -s -X POST \
http://127.0.0.1:10001/playwright/execute -H 'Content-Type: application/json' \
--data-binary @payload.json . The response's 'result' field holds whatever \
your code returns. Do not use any other tool (e.g. a direct HTTP fetch) to \
read page content -- you must go through the live browser."
cd /tmp
/usr/local/bin/fx ask --yolo --no-save --json --system "$SYSTEM_PROMPT" \
"Go to https://news.ycombinator.com and tell me the top 5 article titles."
EOF
kernel browsers fs upload "$SESSION_ID" --file /tmp/run_fx.sh:/tmp/run_fx.sh
kernel browsers process exec "$SESSION_ID" --command chmod --args +x --args /tmp/run_fx.sh

kernel browsers process exec "$SESSION_ID" \
--env "AI_GATEWAY_API_KEY=$AI_GATEWAY_API_KEY" \
--env "FX_MODEL=anthropic/claude-sonnet-4.5" \
--timeout 90 \
--command /tmp/run_fx.sh

kernel browsers delete "$SESSION_ID"