← Back to PRs

#12075: feat(browser): session-aware context isolation for multi-agent browser use

by xiaoyaner0201 open 2026-02-08 20:22 View on GitHub →
channel: discord agents stale
## Summary Add browser session isolation so multiple sessions/sub-agents can use the browser simultaneously without tab/state conflicts, while sharing login state (cookies) from the main context. ## Problem Currently, the browser module uses a global singleton for role-ref caching and page state. When multiple agents/sessions operate tabs concurrently, they overwrite each other's cached refs, leading to stale references and "element not found" errors (#3605, #8157). ## Solution Introduce a **Session-aware Context Registry** pattern — lightweight session isolation that scopes role-ref caches per caller while sharing the underlying CDP connection and browser contexts. ### Phase 1 — Session Context Registry (`pw-session.ts`) - `SessionContext` type with `roleRefsByTarget`, `pageStateOverrides`, `cookies` - Auto-cleanup: 30min expiry, max 100 sessions - Default session `__default__` for backward compatibility ### Phase 2 — Session-aware Role Refs (`pw-tools-core.snapshot.ts`) - All snapshot functions accept optional `sessionId` - Dual cache strategy: session-scoped + global fallback - `restoreRoleRefsForTarget` prioritizes session cache, falls back to global ### Phase 3 — Cookie Inheritance (`pw-session.ts`) - `captureCookiesFromBrowser` / `applyCookiesToBrowser` for state transfer - `inheritCookiesFromDefault` lets sub-agents share login state - `cloneSessionContext` / `copyCookiesBetweenSessions` utilities ### Phase 4 — Full Route Integration - `BrowserRequest` type extended with `sessionId` field - `getSessionId()` helper: extracts sessionId from body, query, or header - All `pw-tools-core.*.ts` functions accept `sessionId` - `agent.act.ts` and `agent.snapshot.ts` routes pass `sessionId` through ## Backward Compatibility All `sessionId` parameters are **optional**. Existing callers that don't pass a sessionId automatically use the `__default__` session, preserving identical behavior. ## Design Choices - **Not full BrowserContext isolation**: CDP `connect()` gets existing contexts; `newContext()` creates new windows. Full isolation would require re-login for each session. - **Dual cache**: Refs stored in both session-scoped and global cache. Session takes priority on read, global serves as fallback for non-session-aware callers. - **Cleanup**: Stale sessions (>30min inactive) are garbage-collected automatically, with a hard cap of 100 concurrent sessions. ## Testing - TypeScript strict-mode compilation passes (`tsc --noEmit`) - Full `pnpm build` succeeds - All changes are additive; no existing function signatures changed Addresses: #3605, #8157 Related: #4663 ## Files Changed (13) | File | Changes | |------|---------| | `pw-session.ts` | +358 (registry + cookies) | | `pw-tools-core.snapshot.ts` | +37 (session-aware refs) | | `pw-tools-core.interactions.ts` | +39 (sessionId passthrough) | | `routes/agent.act.ts` | +29 (route integration) | | `routes/agent.shared.ts` | +28 (getSessionId helper) | | `routes/agent.snapshot.ts` | +13 | | `routes/types.ts` | +2 | | Other pw-tools-core files | +1-8 each | <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR extends Discord messaging/thread tooling to support richer outbound payloads and forum-thread creation: - Adds passthrough `embeds` and `components` fields to message send flows (tool schema → action handler → Discord send helpers). - Enhances `readStringArrayParam` to accept JSON-array strings and comma-separated strings in addition to native arrays. - Extends thread-create flows to optionally include initial post `content` and `appliedTagIds` (intended for forum posts). Main integration points are the agent tool schemas (`src/agents/tools/message-tool.ts`), the Discord action handlers (`src/agents/tools/discord-actions-messaging.ts`, `src/channels/plugins/actions/discord/handle-action.ts`), and the Discord REST wrappers (`src/discord/send.*.ts`). <h3>Confidence Score: 3/5</h3> - This PR is close, but has a functional issue that can break thread creation in some Discord channel types. - Most changes are additive and plumb optional fields through safely, but `createThreadDiscord` currently throws whenever `content` is omitted and `messageId` is absent, which can block valid non-forum thread creation paths. - src/discord/send.messages.ts <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs