Quickstart
From key to first run in five minutes.
Authenticate, run a goal, then drop the engine into your agent over MCP, LangChain, AutoGen, or raw REST.
1 · Authenticate
Send a Bearer key on every request.
Create a per-tenant key in the dashboard. The raw value is shown once — store it as a server-side secret.
Authenticationhttp
Authorization: Bearer ab_live_…
# Keys are per-tenant and shown once. Create one in the dashboard
# after signing up, then keep it server-side.2 · Run a goal
POST /api/v1/run with a url, prompt, and success condition.
The engine perceives the page as indexed state, plans, acts, and returns the path it took. `success` is a structured check — urlIncludes, statusText, textVisible, allOf, anyOf.
Run a goalbash
curl https://twin-browser.com/api/v1/run \
-H "Authorization: Bearer ab_live_…" \
-H "Content-Type: application/json" \
-d '{
"url": "https://app.acme.com/invoices",
"prompt": "export last month as CSV",
"success": { "urlIncludes": "/exports" }
}'
# → 200 { "success": true, "path": [ … ], "indexedState": { … } }
# Unauthorized host → 403. The target must be on your allowlist.3 · MCP server
Expose the engine to Claude and other MCP clients.
A stdio MCP server wraps the REST API with four tools — run_goal, compile_skill, run_skill, and list_skills. Every target-bearing call still passes through the allowlist server-side.
MCP serverbash
# Start the REST engine, then the MCP server over stdio
npm run exec # REST API (the MCP tools call this)
npm run exec:mcp # MCP server (stdio)
# Or run it ad-hoc
npx twin-browser-mcp
# Tools exposed to the agent:
# run_goal url, prompt, success → indexed state + result
# compile_skill url, prompt, name? → a reusable deterministic skill
# run_skill name, url → zero-LLM replay
# list_skills4 · LangChain / AutoGen
Add the browser layer in one line.
`makeTwinBrowserTools()` returns framework-agnostic tool descriptors over the shared client — no heavy dependency, no replay logic reimplemented.
LangChain adapterts
import { DynamicStructuredTool } from "@langchain/core/tools";
import { makeTwinBrowserTools } from "twin-browser";
// One line — framework-agnostic descriptors over the same REST engine.
const tools = makeTwinBrowserTools({ baseUrl: process.env.TWIN_BROWSER_URL })
.map((t) => new DynamicStructuredTool(t));
// The same descriptors' func (object arg → Promise<string>) work in AutoGen too.