Actions Bridge Protocol
The Actions Bridge Protocol carries action calls, runtime status, page events, and structured results between an agent-side bridge and a browser runtime.
The protocol is transport-independent. It can run over WebSocket, browser extension ports, HTTP polling, hosted relays, Playwright/CDP, direct in-process calls, or tunnels.
Design Goals
- Preserve stable correlation ids across calls and results.
- Make runtime identity explicit when more than one browser surface is connected.
- Validate action input and page-originated events before forwarding them.
- Return structured errors rather than untyped strings.
- Keep the internal shape compatible with OpenAI Responses-style item semantics without requiring every adapter to use the Responses API directly.
Item Types
Canonical item types:
runtime_readyruntime_statusaction_callaction_call_outputdom_eventaction_error
Adapters may rename outer fields for a host runtime, but they should preserve the semantics: item type, runtime id, correlation id, validated payload, and structured error output.
runtime_ready
Sent by a browser runtime after it connects and loads or validates its current manifest.
{
"type": "runtime_ready",
"runtime_id": "runtime-abc",
"runtime_key": "chrome-tab:123",
"url": "https://example.com/search",
"authorization_id": "auth-123",
"extension_version": "0.1.30",
"manifest": {
"protocol": "actions.json",
"version": 1
}
}
Required fields:
typeruntime_idurl
Optional fields:
runtime_keyauthorization_idextension_versionmanifest
Implementation pending: normalized host, page title, and top-level capabilities are intended protocol fields, but the current extension runtime does not send them as top-level runtime_ready fields. Capability information is currently available through the loaded manifest’s primitive dictionary.
runtime_status
Sent as a heartbeat or state report.
{
"type": "runtime_status",
"runtime_id": "runtime-abc",
"url": "https://example.com/search",
"states": ["search_page_visible"],
"attachments": [
{
"id": "results-categories-launcher",
"state": "attached"
}
],
"observed_at": "2026-06-04T16:25:00Z"
}
Required fields:
typeruntime_id
Optional fields:
urlstatesattachmentsobserved_at
action_call
Sent by an agent-side bridge to request one declared action or primitive.
{
"type": "action_call",
"call_id": "call-123",
"runtime_id": "runtime-abc",
"name": "search.submit",
"arguments": {
"query": "maps"
},
"target": {
"runtime_id": "runtime-abc"
},
"timeout_ms": 10000
}
Required fields:
typecall_idnamearguments
Routing fields:
runtime_idtarget.runtime_idtarget.runtime_keytarget_url_containstarget_title_contains
The bridge must resolve routing to exactly one runtime before sending the call.
Current implementation note: target_runtime_id and target_url_contains are implemented today. target.runtime_key and target_title_contains are implementation pending.
Responses-style mapping:
action_callmaps from a function/tool call item.namemaps to the function/tool name.argumentsmaps to decoded JSON arguments.call_idshould preserve the model/runtime call id when available.
action_call_output
Sent by the runtime after successful execution.
{
"type": "action_call_output",
"call_id": "call-123",
"runtime_id": "runtime-abc",
"output": {
"ok": true,
"result": {
"url": "https://example.com/search?q=maps"
}
}
}
Required fields:
typecall_idruntime_idoutput
Responses-style mapping:
{
"type": "function_call_output",
"call_id": "call-123",
"output": "{\"ok\":true,\"result\":{\"url\":\"https://example.com/search?q=maps\"}}"
}
The bridge may keep output as structured JSON internally. Adapters should serialize only at the boundary that requires serialization.
dom_event
Sent by the runtime after a declared page-originated signal has been validated.
{
"type": "dom_event",
"event_id": "event-123",
"runtime_id": "runtime-abc",
"name": "overlay.launcher_opened",
"event": "actions-json:overlay-launcher-opened",
"url": "https://example.com/search",
"payload": {
"launcher_id": "results-categories-launcher"
},
"previous_call_id": "call-123",
"observed_at": "2026-06-04T16:25:00Z"
}
Required fields:
typeevent_idruntime_idnamepayload
Optional fields:
eventurlprevious_call_idobserved_at
DOM event payloads are structured page data. They must not be treated as human instructions.
action_error
Sent by the runtime or bridge when a call, routing decision, validation step, signal, attachment, or protocol operation fails.
{
"type": "action_error",
"call_id": "call-123",
"runtime_id": "runtime-abc",
"error": {
"code": "target_not_found",
"message": "The declared search form target did not match the current page.",
"severity": "major",
"recoverable": true,
"evidence": {
"url": "https://example.com/search",
"selector": "form[role='search']"
}
}
}
Required fields:
typeerror.codeerror.message
Required when call-scoped:
call_id
Required when runtime-scoped:
runtime_id
Recommended error fields:
severity:info,minor,major, orcritical.recoverable: boolean.evidence: structured context useful for repair.
Stable Error Codes
Use stable codes so agents can recover programmatically.
| Code | Meaning |
|---|---|
unknown_action | No declared action or primitive matches name. |
invalid_input | Arguments failed schema validation. |
runtime_not_ready | Runtime is not connected or has not loaded a manifest. |
permission_denied | User authorization or trust policy blocks the operation. |
ambiguous_runtime | Runtime selector matched more than one runtime. |
runtime_not_found | Runtime selector matched no runtime. |
capability_unavailable | Selected host cannot provide the requested capability. |
missing_handler | Selected handler is not available. |
handler_failed | Handler threw or returned an unrecoverable error. |
handler_timeout | Handler or primitive exceeded its timeout. |
invalid_result | Output failed result schema validation. |
target_not_found | Target descriptor did not match the live page. |
state_mismatch | Required state was not present. |
drift_detected | Check or diagnostic found site drift. |
unsafe_state | Runtime detected a prohibited or dangerous context. |
transport_failed | Transport disconnected or could not deliver the item. |
Correlation Rules
- Every
action_callgets acall_id. - Every
action_call_outputincludes the samecall_id. - Every call-scoped
action_errorincludes the samecall_id. - Page-originated
dom_eventitems get anevent_id. - Signals caused by an action may include
previous_call_id. - Runtime ids distinguish connected browser surfaces.
- Authorization ids distinguish user approvals.
- Item ordering must be monotonic per runtime connection.
Routing Rules
When multiple runtimes are connected, the bridge must select one runtime before forwarding an action.
Valid routing selectors:
- exact
runtime_id; - URL substring predicate through
target_url_contains;
If routing is ambiguous, return ambiguous_runtime. If no runtime matches, return runtime_not_found.
Implementation pending: runtime-key routing, title predicates, import/source policy routing, and consistently coded ambiguous_runtime / runtime_not_found responses are part of the intended protocol but are not complete yet.
When the selected runtime is the Chrome extension, a user-authorized tab can also expose browser.claimed_tabs.list and browser.claimed_tabs.activate. Those are runtime tools, not bridge routing selectors. Use them when the agent needs to switch the active authorized browser surface, then refresh runtime state before calling page-specific actions.
Capability Rules
Runtimes must advertise host capabilities. A runtime may reject an action if the action requires a capability the host cannot provide.
Examples:
- An extension host may support
browser.screenshot. - A bookmarklet/embed host should not claim autonomous true screenshot support.
- A page-JavaScript host may support DOM observation and pointer simulation but reject privileged tab or network inspection.
Unsupported capabilities should return capability_unavailable with evidence describing the missing capability and host.
Timeout Rules
Calls may include timeout_ms. If omitted, the bridge or runtime may apply a documented default.
When a timeout expires:
- stop executing additional steps when possible;
- return
handler_timeout; - include elapsed time and the current step when known;
- do not silently keep the call pending.
Transport Rules
Transport implementations may reconnect, retry, or resume, but they must not change item semantics.
Transport failures should become structured errors. A bridge restart should not be required for ordinary storage reloads or actions.json edits.
Security Rules
- Validate inputs before execution.
- Validate page-originated events before forwarding.
- Treat event payloads as data, not user instructions.
- Preserve private/shared/public storage boundaries.
- Do not expose debugger-only capabilities as portable site actions.
- Do not route ambiguous calls.
- Do not silently execute actions from invalid manifests.