#12075: feat(browser): session-aware context isolation for multi-agent browser use
channel: discord
agents
stale
Cluster:
Session Management Enhancements
## 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
#15244: feat: Thread-session binding — route sub-agent I/O through platform...
by spk-alex · 2026-02-13
78.8%
#20078: feat(session): Add channelGroups config(optional config) for shared...
by demarlik01 · 2026-02-18
76.9%
#15493: feat(telegram): session state memory for diagnostic continuity
by tangcruz · 2026-02-13
76.1%
#15744: fix: allow cross-agent session path validation
by scottgl9 · 2026-02-13
75.6%
#20081: feat: post-compaction triage UX — fuzzy ok + stage-2 gate + Discord...
by PrivacySmurf · 2026-02-18
75.0%
#22798: feat(webchat): ChatGPT-style multi-chat threads with generated titles
by opnsec · 2026-02-21
75.0%
#10998: fix(agents): pass session thinking/reasoning levels to session_stat...
by wony2 · 2026-02-07
74.9%
#3368: fix: sessions navigation, DM thread display, and DM thread delivery...
by Lukavyi · 2026-01-28
74.7%
#9085: fix: improve stability for terminated responses and telegram retries
by vladdick88 · 2026-02-04
74.7%
#15176: fix(sessions): allow channel-routed session IDs and cross-agent paths
by cathrynlavery · 2026-02-13
74.5%