web-agent-bridge 1.1.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/LICENSE +21 -21
  2. package/README.ar.md +446 -446
  3. package/README.md +780 -844
  4. package/bin/cli.js +80 -80
  5. package/bin/wab.js +80 -80
  6. package/examples/bidi-agent.js +119 -119
  7. package/examples/mcp-agent.js +94 -94
  8. package/examples/next-app-router/README.md +44 -0
  9. package/examples/puppeteer-agent.js +108 -108
  10. package/examples/saas-dashboard/README.md +55 -0
  11. package/examples/shopify-hydrogen/README.md +74 -0
  12. package/examples/vision-agent.js +171 -171
  13. package/examples/wordpress-elementor/README.md +77 -0
  14. package/package.json +69 -78
  15. package/public/.well-known/ai-assets.json +59 -0
  16. package/public/admin/login.html +84 -84
  17. package/public/ai.html +196 -0
  18. package/public/cookies.html +208 -208
  19. package/public/css/premium.css +317 -0
  20. package/public/css/styles.css +1235 -1235
  21. package/public/dashboard.html +704 -704
  22. package/public/demo.html +259 -0
  23. package/public/docs.html +585 -585
  24. package/public/feed.xml +89 -0
  25. package/public/index.html +495 -332
  26. package/public/js/auth-nav.js +31 -31
  27. package/public/js/auth-redirect.js +12 -12
  28. package/public/js/cookie-consent.js +56 -56
  29. package/public/js/wab-demo-page.js +721 -0
  30. package/public/js/ws-client.js +74 -74
  31. package/public/llms-full.txt +309 -0
  32. package/public/llms.txt +85 -0
  33. package/public/login.html +83 -83
  34. package/public/openapi.json +580 -0
  35. package/public/premium-dashboard.html +2487 -0
  36. package/public/premium.html +791 -0
  37. package/public/privacy.html +295 -295
  38. package/public/register.html +103 -103
  39. package/public/robots.txt +87 -0
  40. package/public/script/wab-consent.d.ts +36 -0
  41. package/public/script/wab-consent.js +104 -0
  42. package/public/script/wab-schema.js +131 -0
  43. package/public/script/wab.d.ts +108 -0
  44. package/public/script/wab.min.js +234 -0
  45. package/public/sitemap.xml +93 -0
  46. package/public/terms.html +254 -254
  47. package/public/video/tutorial.mp4 +0 -0
  48. package/script/ai-agent-bridge.js +1558 -1513
  49. package/sdk/README.md +55 -55
  50. package/sdk/index.d.ts +118 -0
  51. package/sdk/index.js +257 -203
  52. package/sdk/package.json +14 -14
  53. package/sdk/schema-discovery.js +83 -0
  54. package/server/config/secrets.js +94 -92
  55. package/server/index.js +0 -9
  56. package/server/middleware/adminAuth.js +30 -30
  57. package/server/middleware/auth.js +41 -41
  58. package/server/middleware/rateLimits.js +24 -24
  59. package/server/migrations/001_add_analytics_indexes.sql +7 -7
  60. package/server/migrations/002_premium_features.sql +418 -0
  61. package/server/models/adapters/index.js +33 -33
  62. package/server/models/adapters/mysql.js +183 -183
  63. package/server/models/adapters/postgresql.js +172 -172
  64. package/server/models/adapters/sqlite.js +7 -7
  65. package/server/models/db.js +561 -561
  66. package/server/routes/admin-premium.js +671 -0
  67. package/server/routes/admin.js +247 -247
  68. package/server/routes/api.js +131 -138
  69. package/server/routes/auth.js +51 -51
  70. package/server/routes/billing.js +45 -45
  71. package/server/routes/discovery.js +406 -329
  72. package/server/routes/license.js +240 -240
  73. package/server/routes/noscript.js +543 -543
  74. package/server/routes/premium-v2.js +686 -0
  75. package/server/routes/premium.js +724 -0
  76. package/server/routes/wab-api.js +476 -476
  77. package/server/services/agent-memory.js +625 -0
  78. package/server/services/email.js +204 -204
  79. package/server/services/fairness.js +420 -420
  80. package/server/services/plugins.js +747 -0
  81. package/server/services/premium.js +1883 -0
  82. package/server/services/self-healing.js +843 -0
  83. package/server/services/stripe.js +192 -192
  84. package/server/services/swarm.js +788 -0
  85. package/server/services/vision.js +871 -0
  86. package/server/utils/cache.js +125 -125
  87. package/server/utils/migrate.js +81 -81
  88. package/server/utils/secureFields.js +50 -50
  89. package/server/ws.js +101 -101
  90. package/docs/DEPLOY.md +0 -118
  91. package/docs/SPEC.md +0 -1540
  92. package/wab-mcp-adapter/README.md +0 -136
  93. package/wab-mcp-adapter/index.js +0 -555
  94. package/wab-mcp-adapter/package.json +0 -17
package/docs/SPEC.md DELETED
@@ -1,1540 +0,0 @@
1
- # WAB Protocol Specification
2
-
3
- **Version:** 1.0
4
- **Status:** Draft
5
- **Date:** 2026-03-25
6
- **Authors:** Web Agent Bridge Contributors
7
- **License:** MIT
8
- **Repository:** [github.com/abokenan444/web-agent-bridge](https://github.com/abokenan444/web-agent-bridge)
9
-
10
- ---
11
-
12
- ## Table of Contents
13
-
14
- 1. [Abstract](#1-abstract)
15
- 2. [Terminology](#2-terminology)
16
- 3. [Protocol Overview](#3-protocol-overview)
17
- 4. [Discovery Protocol](#4-discovery-protocol)
18
- 5. [Command Protocol](#5-command-protocol)
19
- 6. [Lifecycle Protocol](#6-lifecycle-protocol)
20
- 7. [Transport Layers](#7-transport-layers)
21
- 8. [Security Model](#8-security-model)
22
- 9. [Fairness Protocol](#9-fairness-protocol)
23
- 10. [MCP Compatibility](#10-mcp-compatibility)
24
- 11. [Conformance](#11-conformance)
25
- 12. [Appendix A: JSON Schema for agent-bridge.json](#appendix-a-json-schema-for-agent-bridgejson)
26
- 13. [Appendix B: Error Codes](#appendix-b-error-codes)
27
- 14. [Appendix C: MIME Types and Headers](#appendix-c-mime-types-and-headers)
28
-
29
- ---
30
-
31
- ## 1. Abstract
32
-
33
- The **Web Agent Bridge (WAB) Protocol** is an open protocol that enables AI agents to interact with websites through a standardized command interface. Where `robots.txt` tells bots what they *cannot* do, WAB tells AI agents what they *can* do — and exactly how to do it.
34
-
35
- WAB functions as **OpenAPI for human-facing pages**. Website owners publish a machine-readable discovery document describing the actions, permissions, and entry points their site exposes. AI agents consume this document, authenticate, and execute commands through a uniform request/response protocol — eliminating the need for DOM scraping, fragile selectors, or reverse-engineered APIs.
36
-
37
- The protocol is transport-agnostic. A single command schema works identically across in-browser JavaScript globals, WebSocket connections, and HTTP REST endpoints. This allows the same agent logic to operate inside a browser tab, from a remote orchestrator, or within a server-to-server pipeline.
38
-
39
- ### Design Goals
40
-
41
- - **Declarative:** Sites declare capabilities; agents discover them at runtime.
42
- - **Secure:** Every interaction is scoped by permissions, rate limits, and session tokens.
43
- - **Fair:** A neutrality layer ensures small and large sites receive equal agent visibility.
44
- - **Interoperable:** WAB maps cleanly onto MCP (Model Context Protocol) for LLM tool use.
45
- - **Simple:** A minimal conforming implementation requires only a JSON file and a `<script>` tag.
46
-
47
- ### Notational Conventions
48
-
49
- The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).
50
-
51
- ---
52
-
53
- ## 2. Terminology
54
-
55
- | Term | Definition |
56
- |---|---|
57
- | **Agent** | An autonomous or semi-autonomous software entity (typically AI-powered) that discovers, plans, and executes actions on websites via the WAB protocol. |
58
- | **Bridge** | The runtime layer on a website that exposes the WAB interface. In the reference implementation this is the `ai-agent-bridge.js` script that creates `window.AICommands`. |
59
- | **Site Owner** | The person or organization that deploys the Bridge on their website and configures its discovery document, permissions, and actions. |
60
- | **Discovery Document** | A JSON file (`agent-bridge.json` or `/.well-known/wab.json`) that describes a site's WAB capabilities, permissions, transport options, and metadata. |
61
- | **Command** | A structured JSON message sent by an Agent to a Bridge requesting a specific operation. |
62
- | **Action** | A named capability exposed by a Bridge (e.g., `search`, `addToCart`, `signup`). Actions are registered by the Site Owner and discovered by Agents at runtime. |
63
- | **Transport** | The communication channel over which Commands flow between Agent and Bridge. WAB defines three transports: JavaScript Global, WebSocket, and HTTP REST. |
64
- | **Session** | A time-bounded, authenticated context linking an Agent to a Bridge. Sessions are identified by tokens and scoped by permissions. |
65
- | **Tier** | The subscription level governing which features and rate limits apply to a site's Bridge instance. Standard tiers are `free`, `starter`, `pro`, and `enterprise`. |
66
- | **Selector** | A CSS selector string identifying a DOM element. Bridges use selectors to map Actions to page elements. |
67
- | **BiDi Interface** | The WebDriver BiDi-compatible interface exposed at `window.__wab_bidi` for structured command exchange within a browser context. |
68
-
69
- ---
70
-
71
- ## 3. Protocol Overview
72
-
73
- ### 3.1 Architecture
74
-
75
- WAB is organized into three layers:
76
-
77
- ```
78
- ┌─────────────────────────────────────────┐
79
- │ Protocol Layer (Spec) │ ← This document
80
- │ Discovery · Commands · Lifecycle │
81
- ├─────────────────────────────────────────┤
82
- │ Runtime Layer (JS SDK) │ ← ai-agent-bridge.js / WABAgent SDK
83
- │ Bridge · Actions · Permissions · Logs │
84
- ├─────────────────────────────────────────┤
85
- │ Transport Layer (Wire) │ ← JS Global / WebSocket / HTTP
86
- │ window.AICommands · ws:// · /api/wab │
87
- └─────────────────────────────────────────┘
88
- ```
89
-
90
- **Protocol Layer** defines the abstract data formats, lifecycle phases, and conformance requirements. It is implementation-agnostic.
91
-
92
- **Runtime Layer** is a concrete JavaScript SDK that implements the Protocol Layer. The reference implementation provides `ai-agent-bridge.js` (site-side Bridge) and `WABAgent` (agent-side SDK).
93
-
94
- **Transport Layer** carries serialized Commands and Responses between Agent and Bridge. All three transports MUST implement the identical Command Protocol defined in [Section 5](#5-command-protocol).
95
-
96
- ### 3.2 Lifecycle Summary
97
-
98
- Every WAB interaction follows a five-phase lifecycle:
99
-
100
- ```
101
- Discover → Authenticate → Plan → Execute → Confirm
102
- ```
103
-
104
- 1. **Discover** — Agent locates and parses the site's Discovery Document.
105
- 2. **Authenticate** — Agent establishes a Session with the Bridge.
106
- 3. **Plan** — Agent reads available Actions and determines an execution strategy.
107
- 4. **Execute** — Agent sends Commands to perform Actions.
108
- 5. **Confirm** — Agent verifies the results of executed Commands.
109
-
110
- Each phase is detailed in [Section 6](#6-lifecycle-protocol).
111
-
112
- ### 3.3 Design Principles
113
-
114
- 1. **Opt-in only.** No site is WAB-enabled unless the Site Owner explicitly deploys a Bridge.
115
- 2. **Least privilege.** Agents receive only the permissions the Site Owner grants.
116
- 3. **Transport symmetry.** A Command sent over HTTP MUST produce the same result as the same Command sent over WebSocket or the JS global.
117
- 4. **Graceful degradation.** If a transport is unavailable, the Agent SHOULD fall back to an alternative transport listed in the Discovery Document.
118
- 5. **Neutrality.** The protocol includes a Fairness Protocol ([Section 9](#9-fairness-protocol)) to prevent concentration of agent traffic.
119
-
120
- ---
121
-
122
- ## 4. Discovery Protocol
123
-
124
- ### 4.1 Discovery Document Location
125
-
126
- A WAB-enabled site MUST serve its Discovery Document at one or both of the following locations:
127
-
128
- | Priority | URL | Content-Type |
129
- |---|---|---|
130
- | 1 (primary) | `https://{host}/agent-bridge.json` | `application/json` |
131
- | 2 (fallback) | `https://{host}/.well-known/wab.json` | `application/json` |
132
-
133
- An Agent MUST attempt the primary URL first. If it returns a non-2xx status, the Agent SHOULD attempt the fallback URL. If both fail, the site MUST be treated as non-WAB-enabled.
134
-
135
- The Discovery Document MAY also be referenced via an HTML `<meta>` tag:
136
-
137
- ```html
138
- <meta name="wab-discovery" content="/agent-bridge.json">
139
- ```
140
-
141
- ### 4.2 Discovery Document Format
142
-
143
- The Discovery Document is a JSON object with the following top-level fields:
144
-
145
- ```json
146
- {
147
- "wab_version": "1.0",
148
- "provider": {
149
- "name": "Acme Restaurant",
150
- "category": "restaurant",
151
- "url": "https://acme-restaurant.com",
152
- "location": {
153
- "city": "Amman",
154
- "country": "JO",
155
- "support_local": true
156
- }
157
- },
158
- "capabilities": {
159
- "commands": [
160
- {
161
- "name": "viewMenu",
162
- "description": "View the restaurant menu",
163
- "trigger": "navigate",
164
- "params": [],
165
- "requiresAuth": false
166
- },
167
- {
168
- "name": "placeOrder",
169
- "description": "Place a food order",
170
- "trigger": "fill_and_submit",
171
- "params": [
172
- { "name": "items", "type": "array", "required": true, "description": "List of menu item IDs" },
173
- { "name": "address", "type": "string", "required": true, "description": "Delivery address" }
174
- ],
175
- "requiresAuth": true
176
- },
177
- {
178
- "name": "searchMenu",
179
- "description": "Search menu items by keyword",
180
- "trigger": "api",
181
- "params": [
182
- { "name": "query", "type": "string", "required": true, "description": "Search term" }
183
- ],
184
- "requiresAuth": false
185
- }
186
- ],
187
- "permissions": {
188
- "readContent": true,
189
- "click": true,
190
- "fillForms": true,
191
- "scroll": true,
192
- "navigate": false,
193
- "apiAccess": true,
194
- "automatedLogin": false,
195
- "extractData": false
196
- },
197
- "tier": "starter"
198
- },
199
- "agent_access": {
200
- "preferred_entry_point": "/menu",
201
- "api_fallback": "https://api.acme-restaurant.com/v1",
202
- "selectors": {
203
- "menu": "#main-menu",
204
- "cart": "#shopping-cart",
205
- "searchInput": "input[name='search']",
206
- "orderForm": "#order-form"
207
- }
208
- },
209
- "fairness_metrics": {
210
- "commission_rate": "0%",
211
- "direct_benefit": "Orders go directly to the restaurant",
212
- "is_independent": true
213
- },
214
- "trust_signatures": [
215
- "sha256:abc123...",
216
- "wab-registry:verified"
217
- ],
218
- "transport": {
219
- "js_global": {
220
- "enabled": true,
221
- "interface": "window.AICommands"
222
- },
223
- "websocket": {
224
- "enabled": true,
225
- "url": "wss://acme-restaurant.com/ws/wab"
226
- },
227
- "http": {
228
- "enabled": true,
229
- "base_url": "/api/wab"
230
- }
231
- },
232
- "security": {
233
- "require_origin_match": true,
234
- "session_ttl": 3600,
235
- "max_rate": 60
236
- }
237
- }
238
- ```
239
-
240
- ### 4.3 Field Definitions
241
-
242
- #### 4.3.1 `wab_version` (REQUIRED)
243
-
244
- A string indicating the WAB protocol version. For this specification, the value MUST be `"1.0"`.
245
-
246
- #### 4.3.2 `provider` (REQUIRED)
247
-
248
- Metadata about the site and its owner.
249
-
250
- | Field | Type | Required | Description |
251
- |---|---|---|---|
252
- | `name` | string | REQUIRED | Human-readable name of the site or business. |
253
- | `category` | string | REQUIRED | Business category (e.g., `"restaurant"`, `"ecommerce"`, `"saas"`, `"news"`). |
254
- | `url` | string | REQUIRED | Canonical URL of the site. |
255
- | `location` | object | OPTIONAL | Physical location. Contains `city` (string), `country` (ISO 3166-1 alpha-2), and `support_local` (boolean). |
256
-
257
- #### 4.3.3 `capabilities` (REQUIRED)
258
-
259
- Describes what the Bridge can do.
260
-
261
- | Field | Type | Required | Description |
262
- |---|---|---|---|
263
- | `commands` | array | REQUIRED | List of Action definitions. See [Section 4.4](#44-action-definition). |
264
- | `permissions` | object | REQUIRED | Map of permission names to booleans. See [Section 4.5](#45-permissions). |
265
- | `tier` | string | OPTIONAL | Subscription tier: `"free"`, `"starter"`, `"pro"`, or `"enterprise"`. Defaults to `"free"`. |
266
-
267
- #### 4.3.4 `agent_access` (RECOMMENDED)
268
-
269
- Hints for agents on how to interact with the site.
270
-
271
- | Field | Type | Required | Description |
272
- |---|---|---|---|
273
- | `preferred_entry_point` | string | OPTIONAL | URL path the agent SHOULD navigate to first. |
274
- | `api_fallback` | string | OPTIONAL | Base URL for a REST API the agent MAY use when DOM interaction is unavailable. |
275
- | `selectors` | object | OPTIONAL | Map of logical names to CSS selectors for key page elements. |
276
-
277
- #### 4.3.5 `fairness_metrics` (RECOMMENDED)
278
-
279
- Transparency data for the Fairness Protocol ([Section 9](#9-fairness-protocol)).
280
-
281
- | Field | Type | Required | Description |
282
- |---|---|---|---|
283
- | `commission_rate` | string | OPTIONAL | Commission charged to the site (e.g., `"0%"`, `"15%"`). |
284
- | `direct_benefit` | string | OPTIONAL | Human-readable description of how the site benefits. |
285
- | `is_independent` | OPTIONAL | boolean | Whether the site is independently owned. |
286
-
287
- #### 4.3.6 `trust_signatures` (OPTIONAL)
288
-
289
- An array of strings representing cryptographic or registry-based trust attestations. Agents MAY use these to verify the authenticity of the Discovery Document.
290
-
291
- #### 4.3.7 `transport` (REQUIRED)
292
-
293
- Declares available Transport Layers. At least one transport MUST be enabled.
294
-
295
- | Field | Type | Description |
296
- |---|---|---|
297
- | `js_global.enabled` | boolean | Whether the JS global interface is available. |
298
- | `js_global.interface` | string | Global variable name (default: `"window.AICommands"`). |
299
- | `websocket.enabled` | boolean | Whether a WebSocket endpoint is available. |
300
- | `websocket.url` | string | Full WebSocket URL. |
301
- | `http.enabled` | boolean | Whether an HTTP REST endpoint is available. |
302
- | `http.base_url` | string | Base URL path for the HTTP transport. |
303
-
304
- #### 4.3.8 `security` (RECOMMENDED)
305
-
306
- | Field | Type | Default | Description |
307
- |---|---|---|---|
308
- | `require_origin_match` | boolean | `true` | Whether the Bridge validates the requesting origin. |
309
- | `session_ttl` | integer | `3600` | Session lifetime in seconds. |
310
- | `max_rate` | integer | `60` | Maximum commands per minute per session. |
311
-
312
- ### 4.4 Action Definition
313
-
314
- Each entry in `capabilities.commands` MUST conform to:
315
-
316
- | Field | Type | Required | Description |
317
- |---|---|---|---|
318
- | `name` | string | REQUIRED | Unique action identifier (alphanumeric, hyphens, underscores). |
319
- | `description` | string | REQUIRED | Human-readable description of the action. |
320
- | `trigger` | string | REQUIRED | Execution method. One of: `"click"`, `"fill_and_submit"`, `"scroll"`, `"api"`, `"navigate"`. |
321
- | `params` | array | REQUIRED | Array of parameter definitions (MAY be empty). |
322
- | `requiresAuth` | boolean | OPTIONAL | Whether the action requires an authenticated session. Defaults to `false`. |
323
-
324
- Each parameter definition:
325
-
326
- | Field | Type | Required | Description |
327
- |---|---|---|---|
328
- | `name` | string | REQUIRED | Parameter name. |
329
- | `type` | string | REQUIRED | JSON Schema type: `"string"`, `"number"`, `"boolean"`, `"array"`, `"object"`. |
330
- | `required` | boolean | REQUIRED | Whether the parameter is mandatory. |
331
- | `description` | string | RECOMMENDED | Human-readable description. |
332
- | `default` | any | OPTIONAL | Default value if not provided. |
333
- | `enum` | array | OPTIONAL | Allowed values. |
334
-
335
- ### 4.5 Permissions
336
-
337
- The `permissions` object uses the following standard keys:
338
-
339
- | Permission | Type | Description |
340
- |---|---|---|
341
- | `readContent` | boolean | Agent MAY read visible text content from the page. |
342
- | `click` | boolean | Agent MAY trigger click events on permitted elements. |
343
- | `fillForms` | boolean | Agent MAY fill and submit form fields. |
344
- | `scroll` | boolean | Agent MAY scroll the page. |
345
- | `navigate` | boolean | Agent MAY navigate to different URLs within the site. |
346
- | `apiAccess` | boolean | Agent MAY call the site's API endpoints. |
347
- | `automatedLogin` | boolean | Agent MAY perform automated authentication flows. |
348
- | `extractData` | boolean | Agent MAY extract and store structured data from the page. |
349
-
350
- A Bridge MUST enforce these permissions at runtime. If an Agent attempts an action that requires a permission set to `false`, the Bridge MUST reject the command with error code `PERMISSION_DENIED`.
351
-
352
- ---
353
-
354
- ## 5. Command Protocol
355
-
356
- ### 5.1 Command Format
357
-
358
- Every command sent from an Agent to a Bridge MUST conform to the following JSON structure:
359
-
360
- ```json
361
- {
362
- "id": "cmd_a1b2c3d4",
363
- "method": "wab.executeAction",
364
- "params": {
365
- "name": "searchMenu",
366
- "data": {
367
- "query": "vegetarian"
368
- }
369
- },
370
- "context": {
371
- "url": "https://acme-restaurant.com/menu",
372
- "sessionToken": "sess_x9y8z7w6",
373
- "timestamp": "2026-03-25T12:00:00Z"
374
- }
375
- }
376
- ```
377
-
378
- | Field | Type | Required | Description |
379
- |---|---|---|---|
380
- | `id` | string | REQUIRED | Unique identifier for this command. The Bridge MUST echo it in the response. |
381
- | `method` | string | REQUIRED | The WAB method to invoke. See [Section 5.3](#53-standard-methods). |
382
- | `params` | object | REQUIRED | Method-specific parameters. MAY be empty `{}`. |
383
- | `context` | object | OPTIONAL | Execution context. Includes `url`, `sessionToken`, and `timestamp`. |
384
-
385
- ### 5.2 Response Format
386
-
387
- Every response from a Bridge to an Agent MUST conform to:
388
-
389
- **Success response:**
390
-
391
- ```json
392
- {
393
- "id": "cmd_a1b2c3d4",
394
- "type": "success",
395
- "result": {
396
- "items": [
397
- { "name": "Falafel Wrap", "price": 5.99 },
398
- { "name": "Veggie Burger", "price": 8.49 }
399
- ],
400
- "total": 2
401
- }
402
- }
403
- ```
404
-
405
- **Error response:**
406
-
407
- ```json
408
- {
409
- "id": "cmd_a1b2c3d4",
410
- "type": "error",
411
- "error": {
412
- "code": "PERMISSION_DENIED",
413
- "message": "Action 'placeOrder' requires authentication"
414
- }
415
- }
416
- ```
417
-
418
- | Field | Type | Required | Description |
419
- |---|---|---|---|
420
- | `id` | string | REQUIRED | Matches the `id` from the originating command. |
421
- | `type` | string | REQUIRED | Either `"success"` or `"error"`. |
422
- | `result` | object | CONDITIONAL | Present when `type` is `"success"`. Method-specific result data. |
423
- | `error` | object | CONDITIONAL | Present when `type` is `"error"`. Contains `code` and `message`. |
424
-
425
- ### 5.3 Standard Methods
426
-
427
- A conforming WAB Bridge MUST implement the following methods:
428
-
429
- #### `wab.discover`
430
-
431
- Returns the site's Discovery Document.
432
-
433
- - **Params:** None.
434
- - **Result:** The full Discovery Document object.
435
-
436
- ```json
437
- { "id": "1", "method": "wab.discover", "params": {} }
438
- ```
439
-
440
- #### `wab.getContext`
441
-
442
- Returns the current Bridge context including version, permissions, and session state.
443
-
444
- - **Params:** None.
445
- - **Result:** `{ version, permissions, session, tier, url }`.
446
-
447
- ```json
448
- { "id": "2", "method": "wab.getContext", "params": {} }
449
- ```
450
-
451
- Response:
452
-
453
- ```json
454
- {
455
- "id": "2",
456
- "type": "success",
457
- "result": {
458
- "version": "1.0.0",
459
- "permissions": { "readContent": true, "click": true, "fillForms": false },
460
- "session": { "authenticated": false, "ttl": 3600 },
461
- "tier": "free",
462
- "url": "https://acme-restaurant.com/menu"
463
- }
464
- }
465
- ```
466
-
467
- #### `wab.getActions`
468
-
469
- Lists all available Actions, optionally filtered by category.
470
-
471
- - **Params:** `{ "category": "string" }` (OPTIONAL).
472
- - **Result:** Array of Action definitions.
473
-
474
- ```json
475
- { "id": "3", "method": "wab.getActions", "params": { "category": "ordering" } }
476
- ```
477
-
478
- #### `wab.executeAction`
479
-
480
- Executes a named Action with the provided parameters.
481
-
482
- - **Params:** `{ "name": "string", "data": {} }` (REQUIRED).
483
- - **Result:** Action-specific result object.
484
-
485
- ```json
486
- {
487
- "id": "4",
488
- "method": "wab.executeAction",
489
- "params": {
490
- "name": "placeOrder",
491
- "data": { "items": ["item_01", "item_02"], "address": "123 Main St" }
492
- },
493
- "context": { "sessionToken": "sess_x9y8z7w6" }
494
- }
495
- ```
496
-
497
- #### `wab.readContent`
498
-
499
- Reads the text content of a page element identified by a CSS selector.
500
-
501
- - **Params:** `{ "selector": "string" }` (REQUIRED).
502
- - **Result:** `{ "text": "string", "html": "string", "selector": "string" }`.
503
- - **Requires permission:** `readContent`.
504
-
505
- ```json
506
- { "id": "5", "method": "wab.readContent", "params": { "selector": "#main-menu" } }
507
- ```
508
-
509
- #### `wab.getPageInfo`
510
-
511
- Returns metadata about the current page and Bridge state.
512
-
513
- - **Params:** None.
514
- - **Result:** `{ title, url, description, bridgeVersion, actionsCount, permissions }`.
515
-
516
- ```json
517
- { "id": "6", "method": "wab.getPageInfo", "params": {} }
518
- ```
519
-
520
- Response:
521
-
522
- ```json
523
- {
524
- "id": "6",
525
- "type": "success",
526
- "result": {
527
- "title": "Acme Restaurant - Menu",
528
- "url": "https://acme-restaurant.com/menu",
529
- "description": "Fresh Mediterranean cuisine",
530
- "bridgeVersion": "1.0.0",
531
- "actionsCount": 5,
532
- "permissions": { "readContent": true, "click": true }
533
- }
534
- }
535
- ```
536
-
537
- #### `wab.authenticate`
538
-
539
- Authenticates an Agent with the Bridge using an API key or token.
540
-
541
- - **Params:** `{ "apiKey": "string", "meta": {} }` (REQUIRED).
542
- - **Result:** `{ "sessionToken": "string", "expiresAt": "ISO 8601", "permissions": {} }`.
543
-
544
- ```json
545
- {
546
- "id": "7",
547
- "method": "wab.authenticate",
548
- "params": {
549
- "apiKey": "wab_key_abc123",
550
- "meta": { "agentName": "ShoppingAssistant", "version": "2.1" }
551
- }
552
- }
553
- ```
554
-
555
- Response:
556
-
557
- ```json
558
- {
559
- "id": "7",
560
- "type": "success",
561
- "result": {
562
- "sessionToken": "sess_x9y8z7w6",
563
- "expiresAt": "2026-03-25T13:00:00Z",
564
- "permissions": { "readContent": true, "click": true, "fillForms": true }
565
- }
566
- }
567
- ```
568
-
569
- #### `wab.subscribe`
570
-
571
- Subscribes to real-time events from the Bridge. Only available on transports that support push messaging (WebSocket, JS global with event listeners).
572
-
573
- - **Params:** `{ "events": ["string"] }` (REQUIRED). Valid events: `"actionExecuted"`, `"permissionChanged"`, `"sessionExpired"`, `"error"`.
574
- - **Result:** `{ "subscriptionId": "string", "events": ["string"] }`.
575
-
576
- ```json
577
- {
578
- "id": "8",
579
- "method": "wab.subscribe",
580
- "params": { "events": ["actionExecuted", "error"] }
581
- }
582
- ```
583
-
584
- #### `wab.ping`
585
-
586
- Health check. Returns immediately to confirm the Bridge is operational.
587
-
588
- - **Params:** None.
589
- - **Result:** `{ "status": "ok", "timestamp": "ISO 8601", "version": "string" }`.
590
-
591
- ```json
592
- { "id": "9", "method": "wab.ping", "params": {} }
593
- ```
594
-
595
- Response:
596
-
597
- ```json
598
- {
599
- "id": "9",
600
- "type": "success",
601
- "result": { "status": "ok", "timestamp": "2026-03-25T12:00:00Z", "version": "1.0.0" }
602
- }
603
- ```
604
-
605
- ### 5.4 Command ID Generation
606
-
607
- Command IDs MUST be unique within a session. Implementations SHOULD use one of:
608
-
609
- - UUIDv4 (e.g., `"550e8400-e29b-41d4-a716-446655440000"`)
610
- - Monotonically increasing integers (e.g., `"1"`, `"2"`, `"3"`)
611
- - Prefixed counters (e.g., `"cmd_001"`, `"cmd_002"`)
612
-
613
- The Bridge MUST NOT reuse command IDs and MUST reject duplicate IDs within the same session with error code `DUPLICATE_COMMAND_ID`.
614
-
615
- ---
616
-
617
- ## 6. Lifecycle Protocol
618
-
619
- ### 6.1 Lifecycle Phases
620
-
621
- Every agent-site interaction follows five ordered phases. Agents MUST complete each phase before advancing to the next.
622
-
623
- ```mermaid
624
- sequenceDiagram
625
- participant A as Agent
626
- participant B as Bridge
627
- participant S as Site
628
-
629
- Note over A,S: Phase 1 — Discovery
630
- A->>S: GET /agent-bridge.json
631
- S-->>A: 200 OK (Discovery Document)
632
-
633
- Note over A,B: Phase 2 — Authentication
634
- A->>B: wab.authenticate({ apiKey, meta })
635
- B-->>A: { sessionToken, expiresAt, permissions }
636
-
637
- Note over A,B: Phase 3 — Planning
638
- A->>B: wab.getActions()
639
- B-->>A: [{ name, description, params, ... }]
640
- A->>B: wab.getPageInfo()
641
- B-->>A: { title, url, actionsCount, ... }
642
- Note over A: Agent plans execution strategy
643
-
644
- Note over A,B: Phase 4 — Execution
645
- A->>B: wab.executeAction({ name, data })
646
- B-->>A: { result }
647
- A->>B: wab.executeAction({ name, data })
648
- B-->>A: { result }
649
-
650
- Note over A,B: Phase 5 — Confirmation
651
- A->>B: wab.readContent({ selector })
652
- B-->>A: { text, html }
653
- A->>B: wab.getPageInfo()
654
- B-->>A: { updated state }
655
- Note over A: Agent verifies outcomes
656
- ```
657
-
658
- ### 6.2 Phase 1: Discovery
659
-
660
- The Agent locates the site's Discovery Document by:
661
-
662
- 1. Fetching `https://{host}/agent-bridge.json`.
663
- 2. If unavailable, fetching `https://{host}/.well-known/wab.json`.
664
- 3. Optionally, parsing the HTML `<meta name="wab-discovery">` tag.
665
-
666
- The Agent MUST validate the document against the WAB JSON Schema ([Appendix A](#appendix-a-json-schema-for-agent-bridgejson)). If the `wab_version` field indicates a version the Agent does not support, it SHOULD terminate gracefully with an informative error.
667
-
668
- The Agent SHOULD cache the Discovery Document for a reasonable duration (RECOMMENDED: 5 minutes). The response MAY include standard HTTP caching headers (`Cache-Control`, `ETag`).
669
-
670
- ### 6.3 Phase 2: Authentication
671
-
672
- If the Discovery Document includes actions where `requiresAuth` is `true`, the Agent MUST authenticate before executing those actions.
673
-
674
- 1. The Agent sends a `wab.authenticate` command with its API key and optional metadata.
675
- 2. The Bridge validates the key and returns a `sessionToken` with an expiration time.
676
- 3. The Agent MUST include the `sessionToken` in the `context` field of all subsequent commands.
677
-
678
- If no actions require authentication, this phase MAY be skipped. The Bridge MUST still accept unauthenticated commands for actions where `requiresAuth` is `false`.
679
-
680
- **Session renewal:** When a session approaches expiration (RECOMMENDED: within 10% of TTL remaining), the Agent SHOULD re-authenticate to obtain a fresh token. The Bridge MUST NOT invalidate the old token until it naturally expires.
681
-
682
- ### 6.4 Phase 3: Planning
683
-
684
- The Agent reads the available actions and Bridge context to formulate an execution plan:
685
-
686
- 1. Call `wab.getActions()` to retrieve the full list of available actions.
687
- 2. Call `wab.getContext()` to understand current permissions and state.
688
- 3. Optionally call `wab.getPageInfo()` for page metadata.
689
-
690
- The Agent SHOULD filter actions by the permissions granted in the session. The Agent MUST NOT attempt to execute actions for which it lacks the required permissions.
691
-
692
- Planning is internal to the Agent. The protocol does not prescribe a planning algorithm — this is where LLM-powered agents apply their reasoning capabilities.
693
-
694
- ### 6.5 Phase 4: Execution
695
-
696
- The Agent sends `wab.executeAction` commands to perform the planned actions:
697
-
698
- 1. Each command targets a single action by `name`.
699
- 2. The `data` field contains the action's required and optional parameters.
700
- 3. The Bridge validates the command against the action's parameter schema.
701
- 4. The Bridge executes the action (clicking elements, filling forms, calling APIs, etc.).
702
- 5. The Bridge returns the result or an error.
703
-
704
- **Sequential vs. parallel:** Agents MAY send multiple commands concurrently if the actions are independent. The Bridge MUST process each command atomically. The Bridge SHOULD document in the Discovery Document if certain actions have ordering dependencies.
705
-
706
- **Rate limiting:** The Bridge MUST enforce the `max_rate` from the security configuration. If an Agent exceeds the rate limit, the Bridge MUST respond with error code `RATE_LIMITED` and a `Retry-After` value.
707
-
708
- ### 6.6 Phase 5: Confirmation
709
-
710
- After execution, the Agent verifies that the intended outcomes occurred:
711
-
712
- 1. Call `wab.readContent()` to verify visible page changes.
713
- 2. Call `wab.getPageInfo()` to check updated page state.
714
- 3. Compare actual results against expected results from the plan.
715
-
716
- Confirmation is RECOMMENDED but not strictly required. Agents that skip confirmation accept the risk of undetected failures.
717
-
718
- ---
719
-
720
- ## 7. Transport Layers
721
-
722
- WAB defines three Transport Layers. Each transport MUST implement the full Command Protocol from [Section 5](#5-command-protocol). A conforming Bridge MUST support at least one transport. A conforming Agent SHOULD support all three.
723
-
724
- ### 7.1 JavaScript Global Transport
725
-
726
- **Identifier:** `js_global`
727
- **Scope:** In-browser (same page as the Bridge)
728
- **Interface:** `window.AICommands` and `window.__wab_bidi`
729
-
730
- This is the primary transport for agents running inside a browser (Puppeteer, Playwright, browser extensions).
731
-
732
- #### 7.1.1 `window.AICommands` (High-Level)
733
-
734
- The `AICommands` object exposes convenience methods that map to WAB standard methods:
735
-
736
- ```javascript
737
- // Get all available actions
738
- const actions = await window.AICommands.getActions();
739
-
740
- // Get a specific action
741
- const action = await window.AICommands.getAction('searchMenu');
742
-
743
- // Execute an action
744
- const result = await window.AICommands.execute('searchMenu', { query: 'vegetarian' });
745
-
746
- // Read page content
747
- const content = await window.AICommands.readContent('#main-menu');
748
-
749
- // Get page info
750
- const info = await window.AICommands.getPageInfo();
751
-
752
- // Authenticate
753
- const session = await window.AICommands.authenticate('wab_key_abc123', { agentName: 'MyAgent' });
754
- ```
755
-
756
- All methods MUST return Promises. Errors MUST be thrown as JavaScript `Error` objects with a `code` property matching the WAB error codes ([Appendix B](#appendix-b-error-codes)).
757
-
758
- #### 7.1.2 `window.__wab_bidi` (BiDi Protocol)
759
-
760
- The BiDi interface provides a lower-level, WebDriver BiDi-compatible transport:
761
-
762
- ```javascript
763
- const response = await window.__wab_bidi.send({
764
- id: 1,
765
- method: 'wab.executeAction',
766
- params: { name: 'searchMenu', data: { query: 'vegetarian' } }
767
- });
768
- ```
769
-
770
- The BiDi interface MUST:
771
- - Accept the standard Command format from [Section 5.1](#51-command-format).
772
- - Return the standard Response format from [Section 5.2](#52-response-format).
773
- - Expose a `getContext()` method returning the current Bridge context.
774
- - Support event subscriptions via `subscribe(events, callback)`.
775
-
776
- #### 7.1.3 Bridge Readiness
777
-
778
- The Bridge MUST signal readiness by dispatching a custom DOM event:
779
-
780
- ```javascript
781
- window.dispatchEvent(new CustomEvent('wab:ready', {
782
- detail: { version: '1.0.0', transport: 'js_global' }
783
- }));
784
- ```
785
-
786
- Agents SHOULD listen for this event or poll for the existence of `window.AICommands` / `window.__wab_bidi`.
787
-
788
- ### 7.2 WebSocket Transport
789
-
790
- **Identifier:** `websocket`
791
- **Scope:** Remote agents, real-time bidirectional communication
792
- **URL:** Declared in `transport.websocket.url`
793
-
794
- #### 7.2.1 Connection
795
-
796
- The Agent establishes a WebSocket connection to the URL specified in the Discovery Document:
797
-
798
- ```javascript
799
- const ws = new WebSocket('wss://acme-restaurant.com/ws/wab');
800
- ```
801
-
802
- Upon connection, the Agent SHOULD send a `wab.authenticate` command as the first message if authentication is required.
803
-
804
- #### 7.2.2 Message Format
805
-
806
- All messages are JSON-encoded text frames. Binary frames MUST NOT be used.
807
-
808
- **Agent → Bridge (Command):**
809
-
810
- ```json
811
- { "id": "cmd_001", "method": "wab.getActions", "params": {} }
812
- ```
813
-
814
- **Bridge → Agent (Response):**
815
-
816
- ```json
817
- { "id": "cmd_001", "type": "success", "result": [...] }
818
- ```
819
-
820
- **Bridge → Agent (Push Event):**
821
-
822
- ```json
823
- { "id": null, "type": "event", "event": "actionExecuted", "data": { "name": "searchMenu" } }
824
- ```
825
-
826
- Push events have a `null` id and `type` set to `"event"`.
827
-
828
- #### 7.2.3 Connection Lifecycle
829
-
830
- - The Bridge SHOULD send a `wab.ping` response every 30 seconds as a heartbeat.
831
- - If the Agent receives no messages for 60 seconds, it SHOULD close and reconnect.
832
- - The Bridge MUST close the connection when the session expires.
833
- - The close frame SHOULD include a reason code: `4001` (session expired), `4002` (rate limited), `4003` (authentication failed).
834
-
835
- ### 7.3 HTTP REST Transport
836
-
837
- **Identifier:** `http`
838
- **Scope:** Server-to-server, stateless interactions
839
- **Base URL:** Declared in `transport.http.base_url`
840
-
841
- #### 7.3.1 Endpoint Mapping
842
-
843
- Each WAB method maps to an HTTP endpoint:
844
-
845
- | WAB Method | HTTP Method | Path |
846
- |---|---|---|
847
- | `wab.discover` | GET | `{base}/discover` |
848
- | `wab.getContext` | GET | `{base}/context` |
849
- | `wab.getActions` | GET | `{base}/actions` |
850
- | `wab.executeAction` | POST | `{base}/execute` |
851
- | `wab.readContent` | POST | `{base}/read` |
852
- | `wab.getPageInfo` | GET | `{base}/page-info` |
853
- | `wab.authenticate` | POST | `{base}/authenticate` |
854
- | `wab.subscribe` | POST | `{base}/subscribe` |
855
- | `wab.ping` | GET | `{base}/ping` |
856
-
857
- #### 7.3.2 Request Format
858
-
859
- **GET requests** pass parameters as query strings:
860
-
861
- ```http
862
- GET /api/wab/actions?category=ordering HTTP/1.1
863
- Host: acme-restaurant.com
864
- Authorization: Bearer sess_x9y8z7w6
865
- X-WAB-Version: 1.0
866
- ```
867
-
868
- **POST requests** pass parameters as JSON bodies:
869
-
870
- ```http
871
- POST /api/wab/execute HTTP/1.1
872
- Host: acme-restaurant.com
873
- Content-Type: application/json
874
- Authorization: Bearer sess_x9y8z7w6
875
- X-WAB-Version: 1.0
876
-
877
- {
878
- "name": "placeOrder",
879
- "data": { "items": ["item_01"], "address": "123 Main St" }
880
- }
881
- ```
882
-
883
- #### 7.3.3 Response Format
884
-
885
- HTTP responses use standard status codes and return the WAB Response format in the body:
886
-
887
- | HTTP Status | WAB Type | Meaning |
888
- |---|---|---|
889
- | 200 | `success` | Command executed successfully. |
890
- | 400 | `error` | Invalid command or parameters. |
891
- | 401 | `error` | Authentication required or failed. |
892
- | 403 | `error` | Permission denied. |
893
- | 404 | `error` | Action not found. |
894
- | 429 | `error` | Rate limited. Includes `Retry-After` header. |
895
- | 500 | `error` | Internal Bridge error. |
896
-
897
- #### 7.3.4 Required Headers
898
-
899
- | Header | Direction | Required | Description |
900
- |---|---|---|---|
901
- | `X-WAB-Version` | Request | REQUIRED | WAB protocol version (`1.0`). |
902
- | `Authorization` | Request | CONDITIONAL | `Bearer {sessionToken}` for authenticated methods. |
903
- | `Content-Type` | Request | CONDITIONAL | `application/json` for POST requests. |
904
- | `X-WAB-Request-Id` | Request | RECOMMENDED | Unique request ID for tracing. |
905
- | `X-WAB-Request-Id` | Response | RECOMMENDED | Echoed from request. |
906
- | `Retry-After` | Response | CONDITIONAL | Seconds to wait (on 429 responses). |
907
-
908
- ---
909
-
910
- ## 8. Security Model
911
-
912
- ### 8.1 Permission Model
913
-
914
- The Bridge enforces a layered permission model:
915
-
916
- 1. **Discovery-level permissions** — Declared in `capabilities.permissions`. These are the maximum permissions the site grants.
917
- 2. **Session-level permissions** — Returned in the `wab.authenticate` response. These MAY be a subset of discovery-level permissions based on the Agent's tier or API key.
918
- 3. **Action-level requirements** — Each action's `requiresAuth` field determines whether a session is needed.
919
-
920
- Permission enforcement is multiplicative: an action is permitted only if ALL applicable permission layers allow it.
921
-
922
- ### 8.2 Sandbox Execution
923
-
924
- Commands that trigger DOM interactions (click, fill, scroll) MUST be executed within a security sandbox:
925
-
926
- 1. **Selector validation:** The Bridge MUST verify that the target selector is not in the `blockedSelectors` list and, if `allowedSelectors` is non-empty, is in the `allowedSelectors` list.
927
- 2. **Action isolation:** Each action MUST be executed atomically. A failure in one action MUST NOT corrupt the state of other pending actions.
928
- 3. **Output sanitization:** The Bridge MUST sanitize all content returned via `wab.readContent` to prevent injection attacks (strip `<script>` tags, event handlers, etc.).
929
-
930
- ### 8.3 Audit Logging
931
-
932
- A conforming Bridge SHOULD maintain an audit log of all commands received and responses sent. Each log entry MUST include:
933
-
934
- | Field | Description |
935
- |---|---|
936
- | `timestamp` | ISO 8601 timestamp. |
937
- | `commandId` | The command's `id` field. |
938
- | `method` | The WAB method invoked. |
939
- | `agentId` | Identifier for the Agent (from session or API key). |
940
- | `origin` | The requesting origin (for JS global and HTTP transports). |
941
- | `status` | `"success"` or `"error"`. |
942
- | `errorCode` | Error code if applicable. |
943
- | `latencyMs` | Time to process the command in milliseconds. |
944
-
945
- Audit logs SHOULD be retained for at least 30 days. Enterprise-tier implementations MAY retain logs for up to 7 years for compliance purposes.
946
-
947
- ### 8.4 Session-Based Authentication
948
-
949
- Sessions provide the primary authentication mechanism:
950
-
951
- 1. An Agent authenticates via `wab.authenticate` with an API key.
952
- 2. The Bridge returns a `sessionToken` with a bounded TTL (default: 3600 seconds).
953
- 3. The Agent includes the token in all subsequent commands.
954
- 4. The Bridge MUST reject commands with expired or invalid tokens with error code `SESSION_EXPIRED` or `INVALID_TOKEN`.
955
-
956
- Session tokens MUST be:
957
- - At least 128 bits of entropy.
958
- - Opaque to the Agent (no embedded claims that the Agent can decode).
959
- - Transmitted only over secure channels (HTTPS, WSS).
960
-
961
- ### 8.5 Origin Validation
962
-
963
- When `security.require_origin_match` is `true`:
964
-
965
- 1. The Bridge MUST validate the `Origin` header on HTTP requests.
966
- 2. The Bridge MUST validate the `document.referrer` or `window.location` for JS global transport.
967
- 3. Commands from non-matching origins MUST be rejected with error code `ORIGIN_MISMATCH`.
968
-
969
- ### 8.6 Rate Limiting
970
-
971
- The Bridge MUST enforce rate limits as declared in `security.max_rate`:
972
-
973
- 1. Rate limits are per-session (authenticated) or per-origin (unauthenticated).
974
- 2. When the limit is exceeded, the Bridge MUST return error code `RATE_LIMITED`.
975
- 3. The response MUST include a `retryAfter` field (seconds) or `Retry-After` HTTP header.
976
- 4. The Bridge SHOULD use a sliding window algorithm for rate calculation.
977
-
978
- ### 8.7 Escalation Protection
979
-
980
- The Bridge MUST prevent privilege escalation:
981
-
982
- 1. An Agent MUST NOT gain permissions beyond those granted at authentication.
983
- 2. Re-authentication MUST NOT expand permissions without Site Owner configuration change.
984
- 3. Session tokens MUST NOT be transferable between Agents.
985
- 4. The Bridge MUST detect and reject replayed commands (duplicate `id` within a session).
986
-
987
- ### 8.8 Command Signing (OPTIONAL)
988
-
989
- For high-security environments, the Bridge MAY require command signing:
990
-
991
- ```json
992
- {
993
- "id": "cmd_001",
994
- "method": "wab.executeAction",
995
- "params": { "name": "transferFunds", "data": { "amount": 100 } },
996
- "context": { "sessionToken": "sess_abc" },
997
- "signature": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
998
- }
999
- ```
1000
-
1001
- The `signature` field is an HMAC-SHA256 of the canonical JSON representation of `method` + `params`, keyed with a shared secret established during authentication.
1002
-
1003
- ---
1004
-
1005
- ## 9. Fairness Protocol
1006
-
1007
- ### 9.1 The Neutrality Layer
1008
-
1009
- The WAB Fairness Protocol is a unique feature that addresses a critical problem in AI-driven commerce: **the tendency for AI agents to preferentially route traffic to large, well-known brands at the expense of small and independent businesses.**
1010
-
1011
- The Fairness Protocol establishes a set of rules and mechanisms that ensure WAB-enabled sites are treated equitably by AI agents, regardless of the site's size, brand recognition, or advertising budget.
1012
-
1013
- ### 9.2 Equal Treatment Requirement
1014
-
1015
- Agents that implement the WAB protocol MUST adhere to the following fairness rules:
1016
-
1017
- 1. **No preferential routing.** An Agent MUST NOT preferentially route users to one WAB-enabled site over another based solely on brand size, popularity metrics, or commercial arrangements between the Agent operator and the site.
1018
- 2. **Capability-based ranking.** When an Agent selects between multiple WAB-enabled sites that can fulfill a user's request, selection MUST be based on **relevance to the user's query**, **capability match** (which site's actions best fulfill the request), and **quality signals** (user ratings, response time, error rate).
1019
- 3. **Transparency of selection.** An Agent SHOULD be able to explain why it selected one site over another. The explanation MUST reference objective criteria, not commercial relationships.
1020
-
1021
- ### 9.3 Discovery Registry
1022
-
1023
- To ensure equal visibility, the WAB ecosystem defines a **Discovery Registry** — a public, decentralized index of WAB-enabled sites:
1024
-
1025
- 1. Any site with a valid Discovery Document MAY register with the Discovery Registry.
1026
- 2. The Registry MUST accept all registrations that pass schema validation and trust verification.
1027
- 3. The Registry MUST NOT charge differential fees based on site size or traffic volume.
1028
- 4. Agents SHOULD use the Discovery Registry as their primary source for finding WAB-enabled sites.
1029
-
1030
- Registry entries contain:
1031
-
1032
- ```json
1033
- {
1034
- "url": "https://acme-restaurant.com",
1035
- "provider": { "name": "Acme Restaurant", "category": "restaurant" },
1036
- "location": { "city": "Amman", "country": "JO" },
1037
- "capabilities_summary": ["viewMenu", "placeOrder", "searchMenu"],
1038
- "fairness_metrics": { "commission_rate": "0%", "is_independent": true },
1039
- "trust_level": "verified",
1040
- "registered_at": "2026-01-15T00:00:00Z"
1041
- }
1042
- ```
1043
-
1044
- ### 9.4 Priority Scoring
1045
-
1046
- When multiple sites can fulfill a request, Agents SHOULD use the following scoring model:
1047
-
1048
- | Factor | Weight | Description |
1049
- |---|---|---|
1050
- | Relevance | 40% | How well the site's capabilities match the user's intent. |
1051
- | Proximity | 20% | Geographic proximity to the user (for location-based services). |
1052
- | Capability depth | 15% | Number and richness of exposed actions. |
1053
- | Quality | 15% | Historical success rate, response time, uptime. |
1054
- | Freshness | 10% | How recently the Discovery Document was updated. |
1055
-
1056
- The following factors MUST NOT influence priority:
1057
-
1058
- - Brand recognition or popularity metrics (Alexa rank, domain authority, etc.).
1059
- - Paid placement or advertising spend.
1060
- - Commercial agreements between the Agent operator and the site.
1061
- - Site traffic volume.
1062
-
1063
- ### 9.5 Commission Transparency
1064
-
1065
- The `fairness_metrics.commission_rate` field provides transparency about intermediary costs:
1066
-
1067
- 1. Sites MUST accurately report their commission rate.
1068
- 2. Agents SHOULD present commission information to users when relevant (e.g., comparing ordering platforms).
1069
- 3. Agents SHOULD prefer direct-to-business sites (commission_rate = "0%") when quality and relevance are equal.
1070
- 4. The `direct_benefit` field SHOULD explain in plain language how the interaction benefits the site owner.
1071
-
1072
- ### 9.6 Independent Verification
1073
-
1074
- To prevent gaming of the Fairness Protocol:
1075
-
1076
- 1. Discovery Documents MAY be signed with a cryptographic key registered in the Discovery Registry.
1077
- 2. Third-party auditors MAY verify that Agent implementations comply with the fairness rules.
1078
- 3. The `trust_signatures` field in the Discovery Document allows sites to present third-party attestations.
1079
- 4. Agents SHOULD log their site selection decisions for auditability.
1080
-
1081
- ### 9.7 Compliance Reporting
1082
-
1083
- Agent operators SHOULD publish periodic fairness reports including:
1084
-
1085
- - Distribution of traffic across site sizes (small / medium / large).
1086
- - Percentage of traffic routed to independent vs. chain businesses.
1087
- - Average commission rate of selected sites.
1088
- - Selection algorithm transparency (open-source or audited).
1089
-
1090
- ---
1091
-
1092
- ## 10. MCP Compatibility
1093
-
1094
- ### 10.1 Overview
1095
-
1096
- The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) provides a standard interface for LLMs to access external tools, resources, and prompts. WAB is designed to be fully compatible with MCP, enabling WAB-enabled sites to be exposed as MCP tools to any LLM.
1097
-
1098
- ### 10.2 WAB → MCP Tool Mapping
1099
-
1100
- Each WAB action maps to an MCP tool:
1101
-
1102
- | WAB Concept | MCP Concept |
1103
- |---|---|
1104
- | Action | Tool |
1105
- | Action name | Tool name |
1106
- | Action params | Tool input schema (JSON Schema) |
1107
- | Action result | Tool output |
1108
- | Discovery Document | Resource |
1109
- | Bridge context | Resource |
1110
-
1111
- A WAB action:
1112
-
1113
- ```json
1114
- {
1115
- "name": "searchMenu",
1116
- "description": "Search menu items by keyword",
1117
- "trigger": "api",
1118
- "params": [
1119
- { "name": "query", "type": "string", "required": true, "description": "Search term" }
1120
- ]
1121
- }
1122
- ```
1123
-
1124
- Maps to an MCP tool:
1125
-
1126
- ```json
1127
- {
1128
- "name": "acme_restaurant__searchMenu",
1129
- "description": "Search menu items by keyword on Acme Restaurant",
1130
- "inputSchema": {
1131
- "type": "object",
1132
- "properties": {
1133
- "query": { "type": "string", "description": "Search term" }
1134
- },
1135
- "required": ["query"]
1136
- }
1137
- }
1138
- ```
1139
-
1140
- ### 10.3 WAB Discovery → MCP Resources
1141
-
1142
- The Discovery Document is exposed as an MCP resource:
1143
-
1144
- ```json
1145
- {
1146
- "uri": "wab://acme-restaurant.com/discovery",
1147
- "name": "Acme Restaurant WAB Discovery",
1148
- "mimeType": "application/json",
1149
- "description": "WAB capabilities for Acme Restaurant"
1150
- }
1151
- ```
1152
-
1153
- Bridge context is exposed as a second resource:
1154
-
1155
- ```json
1156
- {
1157
- "uri": "wab://acme-restaurant.com/context",
1158
- "name": "Acme Restaurant Bridge Context",
1159
- "mimeType": "application/json"
1160
- }
1161
- ```
1162
-
1163
- ### 10.4 Bidirectional Bridge
1164
-
1165
- A WAB-MCP bridge implementation MUST support both directions:
1166
-
1167
- **WAB → MCP (Site as Tool Provider):**
1168
- 1. Read the site's Discovery Document.
1169
- 2. For each action, generate an MCP tool definition.
1170
- 3. When the LLM calls a tool, translate it to a `wab.executeAction` command.
1171
- 4. Return the WAB response as the MCP tool output.
1172
-
1173
- **MCP → WAB (LLM as Agent):**
1174
- 1. The LLM receives WAB tools via MCP.
1175
- 2. The LLM decides which tool to call based on the user's request.
1176
- 3. The MCP server translates the tool call to a WAB command.
1177
- 4. The WAB response is returned to the LLM.
1178
-
1179
- ### 10.5 MCP Server Implementation
1180
-
1181
- A reference MCP server for WAB SHOULD implement:
1182
-
1183
- ```typescript
1184
- interface WABMCPServer {
1185
- // List WAB sites as MCP tools
1186
- listTools(): Tool[];
1187
-
1188
- // Execute a WAB action via MCP tool call
1189
- callTool(name: string, arguments: object): ToolResult;
1190
-
1191
- // List WAB discovery documents as MCP resources
1192
- listResources(): Resource[];
1193
-
1194
- // Read a WAB resource
1195
- readResource(uri: string): ResourceContent;
1196
- }
1197
- ```
1198
-
1199
- The MCP server MUST:
1200
- - Namespace tool names to avoid collisions (e.g., `{site}__{action}`).
1201
- - Map WAB error codes to MCP error responses.
1202
- - Respect WAB rate limits and propagate `Retry-After` information.
1203
- - Cache Discovery Documents according to [Section 6.2](#62-phase-1-discovery).
1204
-
1205
- ---
1206
-
1207
- ## 11. Conformance
1208
-
1209
- ### 11.1 Conformance Levels
1210
-
1211
- This specification defines two conformance levels:
1212
-
1213
- | Level | Role | Description |
1214
- |---|---|---|
1215
- | **WAB Bridge** | Site-side | A site that implements the WAB protocol for agent consumption. |
1216
- | **WAB Agent** | Agent-side | An agent that consumes WAB-enabled sites according to the protocol. |
1217
-
1218
- ### 11.2 Bridge Conformance Requirements
1219
-
1220
- A conforming WAB Bridge:
1221
-
1222
- 1. MUST serve a valid Discovery Document at `/agent-bridge.json` or `/.well-known/wab.json`.
1223
- 2. MUST support at least one transport layer (JS global, WebSocket, or HTTP).
1224
- 3. MUST implement all standard methods defined in [Section 5.3](#53-standard-methods).
1225
- 4. MUST enforce the permission model defined in [Section 8.1](#81-permission-model).
1226
- 5. MUST enforce rate limits as declared in the Discovery Document.
1227
- 6. MUST return responses conforming to the Response Format in [Section 5.2](#52-response-format).
1228
- 7. MUST reject commands with invalid or expired session tokens.
1229
- 8. MUST use error codes from [Appendix B](#appendix-b-error-codes).
1230
- 9. SHOULD implement audit logging as described in [Section 8.3](#83-audit-logging).
1231
- 10. SHOULD implement sandbox execution as described in [Section 8.2](#82-sandbox-execution).
1232
- 11. MAY implement the WebSocket and HTTP transports in addition to the JS global.
1233
- 12. MAY implement command signing as described in [Section 8.8](#88-command-signing-optional).
1234
-
1235
- ### 11.3 Agent Conformance Requirements
1236
-
1237
- A conforming WAB Agent:
1238
-
1239
- 1. MUST discover sites via the Discovery Document before interacting.
1240
- 2. MUST respect all permissions declared in the Discovery Document.
1241
- 3. MUST NOT execute actions for which it lacks permission.
1242
- 4. MUST authenticate before executing actions that require authentication.
1243
- 5. MUST respect rate limits and honor `Retry-After` directives.
1244
- 6. MUST follow the lifecycle phases defined in [Section 6](#6-lifecycle-protocol).
1245
- 7. MUST use the Command Format from [Section 5.1](#51-command-format).
1246
- 8. SHOULD support all three transport layers.
1247
- 9. SHOULD implement the Fairness Protocol from [Section 9](#9-fairness-protocol).
1248
- 10. SHOULD cache Discovery Documents to reduce load on sites.
1249
- 11. SHOULD implement graceful degradation across transport layers.
1250
- 12. MAY implement command signing for high-security interactions.
1251
-
1252
- ### 11.4 RFC 2119 Requirement Summary
1253
-
1254
- | Keyword | Count | Meaning |
1255
- |---|---|---|
1256
- | MUST | Core requirements | The implementation is non-conforming if violated. |
1257
- | MUST NOT | Prohibitions | The implementation is non-conforming if this occurs. |
1258
- | SHOULD | Strong recommendations | May be ignored with good reason, but implications must be understood. |
1259
- | SHOULD NOT | Discouraged practices | May be done with good reason, but implications must be understood. |
1260
- | MAY | Optional features | Truly optional; implementations may include or omit. |
1261
-
1262
- ---
1263
-
1264
- ## Appendix A: JSON Schema for agent-bridge.json
1265
-
1266
- ```json
1267
- {
1268
- "$schema": "https://json-schema.org/draft/2020-12/schema",
1269
- "$id": "https://webagentbridge.com/schemas/agent-bridge.json",
1270
- "title": "WAB Discovery Document",
1271
- "description": "Schema for the Web Agent Bridge discovery document (agent-bridge.json)",
1272
- "type": "object",
1273
- "required": ["wab_version", "provider", "capabilities", "transport"],
1274
- "properties": {
1275
- "wab_version": {
1276
- "type": "string",
1277
- "const": "1.0",
1278
- "description": "WAB protocol version"
1279
- },
1280
- "provider": {
1281
- "type": "object",
1282
- "required": ["name", "category", "url"],
1283
- "properties": {
1284
- "name": { "type": "string", "minLength": 1 },
1285
- "category": { "type": "string", "minLength": 1 },
1286
- "url": { "type": "string", "format": "uri" },
1287
- "location": {
1288
- "type": "object",
1289
- "properties": {
1290
- "city": { "type": "string" },
1291
- "country": { "type": "string", "pattern": "^[A-Z]{2}$" },
1292
- "support_local": { "type": "boolean" }
1293
- }
1294
- }
1295
- }
1296
- },
1297
- "capabilities": {
1298
- "type": "object",
1299
- "required": ["commands", "permissions"],
1300
- "properties": {
1301
- "commands": {
1302
- "type": "array",
1303
- "items": {
1304
- "type": "object",
1305
- "required": ["name", "description", "trigger", "params"],
1306
- "properties": {
1307
- "name": {
1308
- "type": "string",
1309
- "pattern": "^[a-zA-Z][a-zA-Z0-9_-]*$"
1310
- },
1311
- "description": { "type": "string", "minLength": 1 },
1312
- "trigger": {
1313
- "type": "string",
1314
- "enum": ["click", "fill_and_submit", "scroll", "api", "navigate"]
1315
- },
1316
- "params": {
1317
- "type": "array",
1318
- "items": {
1319
- "type": "object",
1320
- "required": ["name", "type", "required"],
1321
- "properties": {
1322
- "name": { "type": "string" },
1323
- "type": { "type": "string", "enum": ["string", "number", "boolean", "array", "object"] },
1324
- "required": { "type": "boolean" },
1325
- "description": { "type": "string" },
1326
- "default": {},
1327
- "enum": { "type": "array" }
1328
- }
1329
- }
1330
- },
1331
- "requiresAuth": { "type": "boolean", "default": false }
1332
- }
1333
- }
1334
- },
1335
- "permissions": {
1336
- "type": "object",
1337
- "properties": {
1338
- "readContent": { "type": "boolean" },
1339
- "click": { "type": "boolean" },
1340
- "fillForms": { "type": "boolean" },
1341
- "scroll": { "type": "boolean" },
1342
- "navigate": { "type": "boolean" },
1343
- "apiAccess": { "type": "boolean" },
1344
- "automatedLogin": { "type": "boolean" },
1345
- "extractData": { "type": "boolean" }
1346
- }
1347
- },
1348
- "tier": {
1349
- "type": "string",
1350
- "enum": ["free", "starter", "pro", "enterprise"],
1351
- "default": "free"
1352
- }
1353
- }
1354
- },
1355
- "agent_access": {
1356
- "type": "object",
1357
- "properties": {
1358
- "preferred_entry_point": { "type": "string" },
1359
- "api_fallback": { "type": "string", "format": "uri" },
1360
- "selectors": {
1361
- "type": "object",
1362
- "additionalProperties": { "type": "string" }
1363
- }
1364
- }
1365
- },
1366
- "fairness_metrics": {
1367
- "type": "object",
1368
- "properties": {
1369
- "commission_rate": { "type": "string" },
1370
- "direct_benefit": { "type": "string" },
1371
- "is_independent": { "type": "boolean" }
1372
- }
1373
- },
1374
- "trust_signatures": {
1375
- "type": "array",
1376
- "items": { "type": "string" }
1377
- },
1378
- "transport": {
1379
- "type": "object",
1380
- "required": [],
1381
- "properties": {
1382
- "js_global": {
1383
- "type": "object",
1384
- "properties": {
1385
- "enabled": { "type": "boolean" },
1386
- "interface": { "type": "string", "default": "window.AICommands" }
1387
- }
1388
- },
1389
- "websocket": {
1390
- "type": "object",
1391
- "properties": {
1392
- "enabled": { "type": "boolean" },
1393
- "url": { "type": "string", "format": "uri" }
1394
- }
1395
- },
1396
- "http": {
1397
- "type": "object",
1398
- "properties": {
1399
- "enabled": { "type": "boolean" },
1400
- "base_url": { "type": "string" }
1401
- }
1402
- }
1403
- },
1404
- "anyOf": [
1405
- { "properties": { "js_global": { "properties": { "enabled": { "const": true } } } } },
1406
- { "properties": { "websocket": { "properties": { "enabled": { "const": true } } } } },
1407
- { "properties": { "http": { "properties": { "enabled": { "const": true } } } } }
1408
- ]
1409
- },
1410
- "security": {
1411
- "type": "object",
1412
- "properties": {
1413
- "require_origin_match": { "type": "boolean", "default": true },
1414
- "session_ttl": { "type": "integer", "minimum": 60, "default": 3600 },
1415
- "max_rate": { "type": "integer", "minimum": 1, "default": 60 }
1416
- }
1417
- }
1418
- }
1419
- }
1420
- ```
1421
-
1422
- ---
1423
-
1424
- ## Appendix B: Error Codes
1425
-
1426
- All WAB error responses MUST use one of the following standard error codes:
1427
-
1428
- | Code | HTTP Status | Description |
1429
- |---|---|---|
1430
- | `INVALID_COMMAND` | 400 | The command is malformed or missing required fields. |
1431
- | `INVALID_PARAMS` | 400 | One or more parameters are invalid or missing. |
1432
- | `INVALID_METHOD` | 400 | The specified method is not recognized. |
1433
- | `AUTHENTICATION_REQUIRED` | 401 | The command requires authentication but no session token was provided. |
1434
- | `INVALID_TOKEN` | 401 | The provided session token is invalid. |
1435
- | `SESSION_EXPIRED` | 401 | The session token has expired. |
1436
- | `PERMISSION_DENIED` | 403 | The Agent lacks permission to perform this action. |
1437
- | `ORIGIN_MISMATCH` | 403 | The request origin does not match the allowed origins. |
1438
- | `ACTION_NOT_FOUND` | 404 | The specified action name does not exist. |
1439
- | `SELECTOR_NOT_FOUND` | 404 | The target DOM element could not be found. |
1440
- | `RATE_LIMITED` | 429 | The Agent has exceeded the rate limit. |
1441
- | `DUPLICATE_COMMAND_ID` | 409 | A command with this ID was already processed in this session. |
1442
- | `SELECTOR_BLOCKED` | 403 | The target selector is in the blocked list. |
1443
- | `EXECUTION_FAILED` | 500 | The action was attempted but failed during execution. |
1444
- | `BRIDGE_ERROR` | 500 | An internal Bridge error occurred. |
1445
- | `TRANSPORT_ERROR` | 502 | The transport layer encountered an error. |
1446
- | `TIMEOUT` | 504 | The command timed out before completing. |
1447
- | `UNSUPPORTED_VERSION` | 400 | The requested WAB protocol version is not supported by this Bridge. |
1448
- | `SANDBOX_VIOLATION` | 403 | The command attempted an operation outside the security sandbox. |
1449
- | `SIGNATURE_INVALID` | 401 | The command signature failed verification. |
1450
-
1451
- Error response structure:
1452
-
1453
- ```json
1454
- {
1455
- "id": "cmd_001",
1456
- "type": "error",
1457
- "error": {
1458
- "code": "RATE_LIMITED",
1459
- "message": "Rate limit exceeded. Maximum 60 requests per minute.",
1460
- "retryAfter": 12
1461
- }
1462
- }
1463
- ```
1464
-
1465
- The `error` object:
1466
-
1467
- | Field | Type | Required | Description |
1468
- |---|---|---|---|
1469
- | `code` | string | REQUIRED | One of the standard error codes above. |
1470
- | `message` | string | REQUIRED | Human-readable error description. |
1471
- | `retryAfter` | integer | CONDITIONAL | Seconds to wait before retrying (on `RATE_LIMITED`). |
1472
- | `details` | object | OPTIONAL | Additional error context for debugging. |
1473
-
1474
- ---
1475
-
1476
- ## Appendix C: MIME Types and Headers
1477
-
1478
- ### C.1 MIME Types
1479
-
1480
- | MIME Type | Usage |
1481
- |---|---|
1482
- | `application/json` | Discovery Document, Command/Response bodies. |
1483
- | `application/vnd.wab+json` | Formal WAB media type (OPTIONAL). Implementations MAY use this for stricter content negotiation. |
1484
- | `text/event-stream` | Server-Sent Events fallback for subscriptions over HTTP (OPTIONAL). |
1485
-
1486
- ### C.2 Standard Headers
1487
-
1488
- #### Request Headers
1489
-
1490
- | Header | Required | Description |
1491
- |---|---|---|
1492
- | `X-WAB-Version` | REQUIRED | Protocol version. Value: `1.0`. |
1493
- | `X-WAB-Request-Id` | RECOMMENDED | Unique request identifier (UUIDv4). |
1494
- | `X-WAB-Agent-Name` | OPTIONAL | Human-readable name of the Agent. |
1495
- | `X-WAB-Agent-Version` | OPTIONAL | Version of the Agent software. |
1496
- | `Authorization` | CONDITIONAL | `Bearer {sessionToken}` for authenticated requests. |
1497
- | `Content-Type` | CONDITIONAL | `application/json` for POST/PUT requests. |
1498
- | `Accept` | RECOMMENDED | `application/json` or `application/vnd.wab+json`. |
1499
-
1500
- #### Response Headers
1501
-
1502
- | Header | Required | Description |
1503
- |---|---|---|
1504
- | `X-WAB-Version` | REQUIRED | Protocol version supported by the Bridge. |
1505
- | `X-WAB-Request-Id` | RECOMMENDED | Echoed from request for correlation. |
1506
- | `X-WAB-Rate-Remaining` | RECOMMENDED | Number of requests remaining in the current rate window. |
1507
- | `X-WAB-Rate-Reset` | RECOMMENDED | Unix timestamp when the rate window resets. |
1508
- | `Retry-After` | CONDITIONAL | Seconds to wait (on 429 responses). |
1509
- | `Content-Type` | REQUIRED | `application/json`. |
1510
-
1511
- ### C.3 CORS Configuration
1512
-
1513
- Bridges serving the HTTP transport MUST configure CORS headers to allow agent access:
1514
-
1515
- ```http
1516
- Access-Control-Allow-Origin: *
1517
- Access-Control-Allow-Methods: GET, POST, OPTIONS
1518
- Access-Control-Allow-Headers: Content-Type, Authorization, X-WAB-Version, X-WAB-Request-Id, X-WAB-Agent-Name, X-WAB-Agent-Version
1519
- Access-Control-Expose-Headers: X-WAB-Version, X-WAB-Request-Id, X-WAB-Rate-Remaining, X-WAB-Rate-Reset, Retry-After
1520
- Access-Control-Max-Age: 86400
1521
- ```
1522
-
1523
- If `security.require_origin_match` is `true`, the Bridge SHOULD replace the wildcard `*` with explicit allowed origins.
1524
-
1525
- ### C.4 Discovery Document HTTP Headers
1526
-
1527
- When serving the Discovery Document, the server SHOULD include:
1528
-
1529
- ```http
1530
- Content-Type: application/json
1531
- Cache-Control: public, max-age=300
1532
- ETag: "v1-abc123"
1533
- X-WAB-Version: 1.0
1534
- ```
1535
-
1536
- ---
1537
-
1538
- *End of WAB Protocol Specification v1.0*
1539
-
1540
- *Copyright 2026 Web Agent Bridge Contributors. Licensed under MIT.*