Browser Extension Architecture
The PraisonAI browser automation uses a 3-layer architecture for AI-powered browser control.The bridge server and extension support ship in the standalone
praisonai-browser package. Install them with pip install "praisonai-browser[server]" (or pip install "praisonai[all]"). The praisonai browser … commands keep working unchanged.Communication Flow
- CLI sends
start_sessionwith goal - Bridge Server routes to Extension
- Extension captures page state (screenshot, elements)
- Extension sends
observationto Bridge - Bridge processes with BrowserAgent (LLM decision)
- Bridge returns
actionto Extension - Extension executes action via CDP
- Loop continues until goal complete
Architecture Diagram
Running the Browser Agent
Message Types
Extension Readiness Wait
Before sendingstart_session, run_browser_agent_with_progress polls the bridge /health endpoint until an extension connects.
The poll caps at min(15.0, timeout) seconds — a caller passing timeout=2.0 waits at most 2 seconds. Set PRAISONAI_BROWSER_SKIP_EXTENSION_WAIT=1 to skip the poll entirely (for unit tests / mocked bridges). See Environment Variables.
Role Registration
Sockets that connect without anOrigin header declare their role with a register message.
Chrome MV3 offscreen documents often omit Origin on ws://127.0.0.1:8765/ws. The bridge classifies such sockets as CLI, so without register the extension pool stays empty and start_session returns NO_EXTENSION.
Send it once, on open:
Success response:
Sockets using a
chrome-extension:// origin (such as the side panel) are already classified as the extension and don’t need to register. The existing Python CLI needs no changes.Troubleshooting
Extension Not Connecting
If you see “Extension did not connect after 15s”:-
Check extension console:
- Go to
chrome://extensions/ - Find “PraisonAI Browser Agent”
- Click “service worker” link
- Look for errors
- Go to
-
Kill stale Chrome processes:
-
Rebuild extension:
-
Check bridge server:
Expected output:
connectionscounts all WebSocket clients (extension, CLI, curl’d probes). Checkextension_connections >= 1instead — it counts only clients whoseOriginstarts withchrome-extension://, so a stray CLI probe won’t make it look connected.connections >= 1alone is no longer sufficient.extension_busyandactive_session_id(added in PraisonAI #3095 hardening) tell you whether the extension is currently owned by a session — a healthy-and-idle bridge showsextension_busy: false.praisonai browser runfails fast with an “Extension already running a session” error rather than hanging when this istrue. Servers older than that commit omit both fields; treat missing asfalse/null.Servers older than PraisonAI #3115 don’t returnextension_connections. The CLI helpers (doctor extension, thelaunchpoller) fall back toconnectionsin that case.
start_session returns NO_EXTENSION even though the WebSocket is open
The offscreen document has not registered. Add this to its onopen handler:
[SERVER][REGISTER] Connection registered as extension. Once the extension has sent register, /health (extension_connections) and session routing agree. If /health shows extension_connections: 1 but start_session still returns NO_EXTENSION, check that the start_session is sent after the registered status and from the expected socket.
No Observations Sent
If session starts but times out:- Check extension console for
[PraisonAI] onStartAutomation FATAL ERROR - CDP debugger may fail to attach
- Page may be a chrome:// URL (unsupported)
Debug Mode
~/.praisonai/browser_screenshots/.

