Skip to content

multi_tab_chat_architecture

github-actions[bot] edited this page Sep 20, 2026 · 1 revision

Multi-Tab Chat Architecture

Multi-tab chat enables parallel, independent agent sessions within a single browser window. This architecture is built on a Session-First principle, ensuring that state is never leaked between tabs.


📋 Core Principles

  1. Session Isolation: Every tab is strictly bound to a unique session_id.
  2. Stateless Components: UI components (ChatArea, Sidebar) derive their entire state from the session configuration in the store.
  3. Unified API Communication: All requests to the agent_go backend must include the X-Session-ID header.

🏗️ Technical Implementation

1. State Management (chatStore.ts)

The global store tracks all active tabs and their configurations:

interface ChatTab {
  id: string;          // session_id
  type: 'chat' | 'workflow';
  config: TabConfig;   // MCP servers, skills, browser settings, etc.
  isRestoring: boolean;
}

2. Race Condition Prevention: sessionsBeingRestored

To prevent duplicate tabs from being created during simultaneous auto-restoration and manual session detection, the system uses a global sessionsBeingRestored Set.

  • Check: Before creating a new tab, the system checks if the ID is in this set.
  • Lock: If not present, it adds the ID and proceeds with tab creation.
  • Release: Once the tab is fully initialized and events have been polled, the ID is removed from the set.

3. API & Event Routing

  • Header Injection: The api.ts service automatically injects the X-Session-ID header into every request.
  • Polling Scoping: The event polling mechanism (PollingProvider) scopes its requests using the active tab's session ID. This ensures that the event stream only contains messages relevant to the current view.
  • Session Stopping: When a tab is closed, the frontend explicitly calls /api/session/stop to terminate any background LLM processes for that specific session.

🔄 Tab Lifecycle

  1. Creation: A tab is created via the "New Chat" button or by clicking a previous session in the history.
  2. Configuration Injection: The TabConfig (selected servers, browser mode, etc.) is loaded from the database or preset.
  3. Active Monitoring: The PollingProvider starts a long-polling loop for that session.
  4. Persistence: Every message and configuration change is persisted to the backend SQLite database in real-time.
  5. Termination: Closing the tab removes it from the UI but keeps the session in history unless explicitly deleted.

🚀 Recent Improvements

  • Strict Tab Activation: Switching tabs now triggers an immediate event poll to ensure the UI is up-to-date.
  • Memory Management: Ephemeral chat tabs (those not yet saved to history) are automatically cleaned up if the user navigates away without sending a message.
  • Cross-Tab Awareness: The "Stop" button in the toolbar correctly identifies which session to terminate, even if multiple agents are running in the background.

⚠️ Known Limitations

  • Browser Tab Isolation: Multi-tab chat works within a single browser tab. Opening the app in two separate browser windows/tabs will create two independent polling loops, which may cause performance overhead on the backend.

Clone this wiki locally