diff --git a/README.md b/README.md index 984d63b..64fb3b4 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/integrations/fx-colocated-agent/README.md b/integrations/fx-colocated-agent/README.md new file mode 100644 index 0000000..cda3ee2 --- /dev/null +++ b/integrations/fx-colocated-agent/README.md @@ -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. diff --git a/integrations/fx-colocated-agent/run.sh b/integrations/fx-colocated-agent/run.sh new file mode 100755 index 0000000..995039b --- /dev/null +++ b/integrations/fx-colocated-agent/run.sh @@ -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\": \"\"} 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"