How GenericAgent Preserves Browser Session State and Login Sessions: A Deep Dive into the TMWebDriver Architecture
GenericAgent maintains browser sessions in memory via a singleton WebDriver instance while serializing login credentials to disk, ensuring that browser tabs and authenticated sessions survive across multiple tool calls and process restarts.
The lsdefine/GenericAgent repository implements a stateful browser automation system that allows LLM agents to interact with web pages without losing context between operations. Unlike ephemeral browser instances that terminate after each action, this architecture preserves both browser session state (open tabs, navigation history) and login sessions (authentication tokens) through persistent in-memory data structures and local file storage.
How Browser Sessions Survive Across Tool Calls
The WebSocket and HTTP Server Architecture
At the core of session persistence lies TMWebDriver, which initializes both a WebSocket server for Chrome DevTools Protocol communication and an HTTP long-poll server for browser extension connectivity. These servers start immediately upon instantiation in TMWebDriver.__init__, creating the infrastructure that maintains persistent connections to browser tabs【TMWebDriver.py#L37-L46】.
Because these servers run continuously within the Python process, they maintain open channels to the browser extension, eliminating the need to re-establish connections for every automation command.
Session Objects and State Tracking
Each browser tab maps to a Session instance that stores critical state metadata. The Session class definition in TMWebDriver.py captures:
id– the unique tab identifierurl– current page locationconnect_at/disconnect_at– activity timestamps for lifecycle managementtype– connection protocol ('ws','ext_ws', or'http')- client reference – either a WebSocket object or HTTP Queue【TMWebDriver.py#L8-L15】
This object-oriented approach ensures that tab-specific state remains accessible throughout the agent's execution, enabling seamless interaction with specific pages across multiple LLM tool invocations.
Registration and Auto-Reconnection Logic
When a browser extension connects (signaled by type == 'ready'), the _register_client method either creates a new Session or updates an existing one. If a tab disconnects unexpectedly, Session.mark_disconnected flags the session while preserving its metadata, allowing the driver to auto-switch to the most recent active tab without losing the session registry【TMWebDriver.py#L65-L75】.
This reconnection tolerance ensures that temporary network interruptions or browser hibernation do not force the agent to restart its browsing workflow.
Automatic Cleanup of Stale Sessions
To prevent memory leaks while preserving valid sessions, TMWebDriver.clean_sessions removes entries disconnected for more than 10 minutes. This background maintenance runs automatically, keeping the session dictionary lean without terminating active tabs that the agent might need to revisit【TMWebDriver.py#L14-L20】.
Default Tab Tracking for Multi-Tab Workflows
The driver maintains self.default_session_id, which points to the currently active tab. This reference updates whenever new tabs arrive or when explicit switching occurs via web_scan or web_execute_js calls【TMWebDriver.py#L41-L43】.
By tracking a default session, the agent can execute JavaScript or capture screenshots without specifying a tab ID every time, streamlining the interaction model while maintaining full multi-tab capability.
Singleton Pattern in ga.py
The ga.py module instantiates a single TMWebDriver object at startup through first_init_driver. All subsequent tool calls—whether scanning pages, executing JavaScript, or navigating URLs—reuse this same driver instance【ga.py#L99-L104】.
Because the driver persists in RAM for the entire process lifetime, the self.sessions dictionary remains intact across all LLM interactions, effectively freezing browser state between reasoning cycles.
Persisting Login Sessions to Disk
WeChat Token Persistence Example
For authentication that must survive process restarts, GenericAgent implements file-based persistence. The WeChat frontend (frontends/wechatapp.py) demonstrates this pattern through its WxBotClient class:
After QR-code authentication succeeds, the _save method writes bot_token and ilink_bot_id to ~/.wxbot/token.json【wechatapp.py#L34-L38】. On subsequent startups, the constructor calls _load to read this file, bypassing the QR login if valid credentials exist【wechatapp.py#L29-L33】.
Generic Pattern for Frontend Authentication
This approach generalizes across any authentication-dependent frontend: store credentials in a user-specific JSON file outside the source tree, then load them during initialization. The agent never embeds secrets in mykey.py or version control; only the local token file holds persistent authentication state.
Practical Implementation Examples
# 1️⃣ Initialise the driver (done automatically by GenericAgent)
from TMWebDriver import TMWebDriver
driver = TMWebDriver() # starts WS & HTTP servers
# 2️⃣ List all active browser tabs – the session IDs are stable
sessions = driver.get_all_sessions()
print(sessions) # [{'id': '12345', 'url': 'https://example.com/...'}, ...]
# 3️⃣ Switch the default tab (e.g. the second tab) before running JS
second_tab_id = sessions[1]['id']
driver.default_session_id = second_tab_id
# 4️⃣ Execute JavaScript in the current default tab
result = driver.execute_js("document.title")
print(result) # {'js_return': 'Example Domain', ...}
# 5️⃣ The driver automatically cleans up dead tabs
driver.clean_sessions() # removes sessions idle >10 min
# -----------------------------------------------------------------
# 6️⃣ WeChat login persistence (run once, then reuse)
from frontends.wechatapp import WxBotClient
bot = WxBotClient()
if not bot.token: # first run – QR login required
bot.login_qr() # stores token in ~/.wxbot/token.json
else:
print("Already logged in as", bot.bot_id) # token read from file
Summary
- In-memory session persistence:
TMWebDrivermaintains asessionsdictionary that maps tab IDs toSessionobjects, surviving across all tool calls within a single process. - Dual-server architecture: WebSocket and HTTP long-poll servers provide robust communication channels that handle reconnections without losing browser context.
- Automatic lifecycle management: The
clean_sessionsmethod prevents memory leaks by purging disconnected tabs after 10 minutes while keeping active sessions intact. - Default tab tracking: The
default_session_idattribute enables seamless multi-tab workflows without explicit tab selection on every operation. - Authentication serialization: Frontend modules like
wechatapp.pydemonstrate persisting login tokens to~/.wxbot/token.json, eliminating redundant authentication after restarts.
Frequently Asked Questions
How does GenericAgent handle browser disconnections?
The TMWebDriver marks disconnected sessions via Session.mark_disconnected but retains their metadata in memory. When the browser extension reconnects, _register_client matches the new connection to existing session data using the tab ID, allowing seamless continuation of interrupted workflows without restarting the browser instance.
Where are login credentials stored?
Login credentials serialize to local JSON files within the user's home directory (e.g., ~/.wxbot/token.json for WeChat). This keeps sensitive data out of the source repository while ensuring that WxBotClient can authenticate immediately upon initialization without requiring manual QR-code scanning on every startup.
Can GenericAgent maintain multiple browser tabs simultaneously?
Yes. The driver maintains a dictionary of Session objects, each representing a distinct browser tab with its own URL, connection type, and client reference. The default_session_id property determines which tab receives commands, but agents can switch contexts dynamically by updating this pointer or addressing specific session IDs directly.
What happens to sessions when the Python process restarts?
Browser sessions (tab states) exist only in RAM and disappear upon process termination, requiring the browser extension to reconnect and re-register tabs. However, login sessions persist because the authentication tokens serialize to disk; the WeChat frontend automatically reloads these credentials via _load, restoring authenticated state without user intervention.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →