Web Agent Bridge (WAB) is an open protocol for discovery, trust, and transactions
between AI agents and websites. Sites publish a signed wab.json manifest declaring what
agents can do; agents discover it via DNS (_wab.<domain> TXT) or HTTPS; every action and
receipt is cryptographically verifiable (Ed25519).
WAB replaces guesswork (DOM scraping, brittle selectors, vision models) with a contract:
scoped, rate-limited, idempotent, and auditable. The browser SDK (wab.min.js) and the
original window.AICommands surface remain available for backward compatibility — see the
Legacy section.
_wab.<domain>) or /.well-known/wab.json.wab.json: capabilities, scopes, public key, version.Make your site discoverable and signed in three steps.
From your project root:
# Generates wab.json + Ed25519 key pair, prints DNS TXT to publish
npx wab-init --site=https://yourdomain.com --yes
wab.jsonHost the generated manifest at https://yourdomain.com/.well-known/wab.json:
{
"schema_version": "wab/1",
"site": "https://yourdomain.com",
"public_key": "ed25519:BASE64...",
"capabilities": [
{ "name": "search", "scope": "public" },
{ "name": "cart.add", "scope": "user", "requires": ["atp:intent"] }
],
"endpoints": {
"atp": "https://yourdomain.com/api/atp"
},
"signature": "ed25519:BASE64..."
}
Add a single TXT record so agents can discover you without scraping HTML:
_wab.yourdomain.com. TXT "v=wab1; pk=ed25519:BASE64...; url=https://yourdomain.com/.well-known/wab.json"
That's it. Any WAB-aware agent can now discover, verify, and transact with your site. Add the optional browser SDK for in-page hints:
<script src="https://cdn.webagentbridge.com/wab.min.js"></script>
window.AIBridgeConfig object and license-key model. They remain
supported but are not the recommended path for new integrations. New work should use the
wab.json manifest + Ed25519 model documented above.
The legacy bridge is configured through the window.AIBridgeConfig object, which must be set before loading the script.
window.AIBridgeConfig = {
// License key from your dashboard
licenseKey: "WAB-XXXXX-XXXXX-XXXXX-XXXXX",
// Subscription tier (verified server-side)
subscriptionTier: "free",
// What AI agents are allowed to do
agentPermissions: {
readContent: true, // Read page text
click: true, // Click elements
fillForms: false, // Fill and submit forms
scroll: true, // Scroll the page
navigate: false, // Navigate between pages
apiAccess: false, // Call internal APIs (Pro+)
automatedLogin: false, // Automated login (Pro+)
extractData: false // Extract structured data (Pro+)
},
// Access restrictions
restrictions: {
allowedSelectors: [], // Empty = allow all
blockedSelectors: [".private", "[data-private]"],
requireLoginForActions: ["apiAccess"],
rateLimit: { maxCallsPerMinute: 60 }
},
// Activity logging
logging: {
enabled: false,
level: "basic" // "basic" or "detailed"
}
};
Permissions control what AI agents can do on your site. Each permission can be independently toggled.
| Permission | Description | Min Tier |
|---|---|---|
readContent | Read text content from page elements | Free |
click | Click buttons, links, and interactive elements | Free |
scroll | Scroll the page or to specific elements | Free |
fillForms | Fill form fields and submit forms | Free |
navigate | Navigate to different pages | Free |
automatedLogin | Perform automated login flows | Pro |
apiAccess | Call internal REST API endpoints | Pro |
extractData | Extract structured data from the page | Pro |
The window.AICommands object provides the following methods:
getActions(category?)Returns an array of all available actions. Optionally filter by category.
const allActions = window.AICommands.getActions();
const navActions = window.AICommands.getActions("navigation");
// Returns: [{ name, description, trigger, category, requiresAuth, params, fields }]
execute(actionName, params?)Execute a registered action. Returns a Promise with the result.
const result = await window.AICommands.execute("signup");
// → { success: true, action: "click", selector: "#signup-button" }
const formResult = await window.AICommands.execute("fill_contact_form", {
name: "Alice",
email: "alice@example.com"
});
// → { success: true, results: [...] }
readContent(selector)Read text content from a DOM element.
const content = window.AICommands.readContent("h1.title");
// → { success: true, text: "Welcome!", html: "Welcome!", attributes: {...} }
getPageInfo()Get metadata about the current page and bridge state.
const info = window.AICommands.getPageInfo();
// → { title, url, domain, lang, bridgeVersion, tier, permissions, actionsCount, rateLimitRemaining }
waitForElement(selector, timeout?)Wait for a DOM element to appear. Useful for SPAs and dynamically loaded content.
await window.AICommands.waitForElement(".results-loaded", 15000);
// Resolves when the element appears, rejects on timeout
registerAction(actionDef)Register a custom action that AI agents can discover and execute.
window.AICommands.registerAction({
name: "addToCart",
description: "Add the current product to cart",
trigger: "click",
selector: "#add-to-cart-btn",
category: "e-commerce",
metadata: { requiresProduct: true }
});
authenticate(agentKey, agentMeta?)Authenticate an AI agent to access restricted actions.
refresh()Re-scan the page and rebuild the action registry. Call this after significant DOM changes.
onReady(callback)Register a callback for when the bridge finishes initialization.
Actions are the core building blocks of WAB. Each action has:
name — Unique identifierdescription — Human/AI readable descriptiontrigger — Type of action: click, fill_and_submit, scroll, apiselector — CSS selector of the target elementfields — Array of form fields (for fill_and_submit actions)category — Grouping labelrequiresAuth — Whether agent authentication is needed| Trigger | Description | Permission |
|---|---|---|
click | Click on an element | click |
fill_and_submit | Fill form fields and submit | fillForms |
scroll | Scroll to an element or direction | scroll |
api | Call an internal API endpoint | apiAccess |
Subscribe to bridge events for monitoring and integration:
const bridge = window.AICommands;
bridge.events.on('ready', (data) => {
console.log('Bridge ready', data.version);
});
bridge.events.on('action:before', ({ action, params }) => {
console.log(`Executing: ${action}`);
});
bridge.events.on('action:after', ({ action, result }) => {
console.log(`Result: ${result.success}`);
});
bridge.events.on('error', (err) => {
console.error('Bridge error', err);
});
Available events: ready, action:before, action:after, action:registered, action:unregistered, agent:authenticate, error, refresh, destroy
If you're building an AI agent that interacts with websites, here's how to use WAB.
// Check if the site supports WAB
if (window.AICommands) {
const info = window.AICommands.getPageInfo();
console.log(`WAB v${info.bridgeVersion} detected`);
console.log(`${info.actionsCount} actions available`);
console.log(`Tier: ${info.tier}`);
} else {
console.log('No WAB support — fall back to DOM parsing');
}
async function agentWorkflow() {
const bridge = window.AICommands;
// 1. Authenticate (if needed)
bridge.authenticate("agent-key-123", {
name: "MyAssistant",
version: "2.0"
});
// 2. Discover available actions
const actions = bridge.getActions();
// 3. Find the action we need
const loginAction = actions.find(a => a.name.includes('login'));
// 4. Execute it
if (loginAction) {
const result = await bridge.execute(loginAction.name, {
email: "user@example.com",
password: "secure-password"
});
console.log(result);
}
// 5. Wait for navigation
await bridge.waitForNavigation();
// 6. Refresh actions for new page
bridge.refresh();
}
WAB is built with security as a first-class concern:
blockedSelectors to protect sensitive areas (forms with credit cards, admin panels)requireLoginForActions restriction for sensitive operationswindow.AIBridgeConfig = {
licenseKey: "WAB-SHOP-XXXXX-XXXXX",
agentPermissions: {
readContent: true,
click: true,
fillForms: true,
scroll: true
},
restrictions: {
blockedSelectors: ["#checkout-payment", ".credit-card-form"],
rateLimit: { maxCallsPerMinute: 30 }
}
};
// After the bridge loads, add custom actions
document.addEventListener('wab:ready', () => {
window.AICommands.registerAction({
name: "searchProducts",
description: "Search for products by keyword",
trigger: "fill_and_submit",
fields: [{ name: "query", selector: "#search-input", type: "text" }],
submitSelector: "#search-btn",
category: "search"
});
});
window.AIBridgeConfig = {
licenseKey: "WAB-SAAS-XXXXX-XXXXX",
subscriptionTier: "pro",
agentPermissions: {
readContent: true,
click: true,
fillForms: true,
apiAccess: true,
extractData: true
}
};
document.addEventListener('wab:ready', () => {
// Custom API action
window.AICommands.registerAction({
name: "getAnalytics",
description: "Fetch analytics data for the current period",
trigger: "api",
endpoint: "/api/analytics/current",
method: "GET",
requiresAuth: true,
category: "data"
});
// Custom handler action
window.AICommands.registerAction({
name: "exportReport",
description: "Generate and download a PDF report",
trigger: "click",
category: "export",
handler: async () => {
const res = await fetch('/api/report/generate');
const blob = await res.blob();
// trigger download...
return { success: true, message: "Report downloaded" };
}
});
});
The WAB server provides a REST API for managing sites, licenses, and analytics.
| Endpoint | Method | Description |
|---|---|---|
POST /api/auth/register | POST | Create a new account |
POST /api/auth/login | POST | Sign in and receive JWT token |
GET /api/auth/me | GET | Get current user info |
| Endpoint | Method | Description |
|---|---|---|
GET /api/sites | GET | List all your sites |
POST /api/sites | POST | Add a new site |
GET /api/sites/:id | GET | Get site details |
PUT /api/sites/:id/config | PUT | Update site configuration |
PUT /api/sites/:id/tier | PUT | Change subscription tier |
DELETE /api/sites/:id | DELETE | Delete a site |
GET /api/sites/:id/snippet | GET | Get install snippet |
GET /api/sites/:id/analytics | GET | Get analytics data |
| Endpoint | Method | Description |
|---|---|---|
POST /api/license/verify | POST | Verify a license key for a domain |
POST /api/license/track | POST | Record an analytics event |
The core script is open source and free forever. Advanced features like API access, detailed analytics, and automated login require a paid subscription.
WAB works with any agent that can execute JavaScript in a browser context — including Selenium, Puppeteer, Playwright, browser extensions, and AI tools like OpenAI's Operator or Anthropic's Computer Use.
Call bridge.refresh() after navigation events to re-scan for new elements. The waitForElement() method helps agents wait for dynamically loaded content.
Yes. Without a license key, WAB runs in free-tier mode with all basic permissions. The licensing server only validates premium features.