Focus Modes Implementation
Focus Modes Implementation Focus modes are temporary system prompt modifications that specialize the AI for specific tasks, treated as tool calls with activa...
Focus Modes Implementation
Focus modes are temporary system prompt modifications that specialize the AI for specific tasks, treated as tool calls with activation/deactivation/restart semantics.
Why This Exists
Allows the LLM to dynamically switch into specialized modes (e.g., “web research”, “code planning”) by modifying the system prompt mid-conversation. Users can reject activation during a countdown or deactivate via context menu.
How It Works
Data Flow
- User sends message -> WebSocket handler extracts
active_focus_idfrom chat metadata - Preprocessor identifies relevant focus modes from available list
- Main Processor generates
activate_focus_mode/deactivate_focus_modetools - LLM decides to call activation/deactivation
- Tool execution -> creates and streams a
focus_mode_activationcountdown embed, stores pending continuation context, and exits cleanly - User decision -> rejection resumes ordinary processing; otherwise auto-confirm publishes
focus_mode_activated - Client persistence -> the first-party client encrypts the focus ID with the chat key and returns the encrypted value for persistence
- Processing restarts with active focus state and the focus-mode prompt in the system prompt
Backend: Tool Generation (main_processor.py)
activate_focus_mode: generated when preprocessor finds relevant focus modes AND no mode is currently active. Parameters include enum of relevant focus mode IDs with descriptions.deactivate_focus_mode: generated whenactive_focus_idis set. No parameters.- Tool names use
system-prefix to distinguish from regular skills. - Relevant focus modes are activation candidates only. They do not set
active_focus_id, enable focus-specific routing, or suppress ordinary preselected skills. - Active Deep research enables and forces its sub-chat delegation policy only after the activation continuation supplies
active_focus_id: web-research.
Backend: Activation Flow
When activate_focus_mode is called:
- Create a
focus_mode_activationembed viaembed_service.create_focus_mode_activation_embed()(TOON-encoded, encrypted, cached, streamed to the client). - Store pending activation context in Redis with a bounded TTL.
- Schedule
focus_mode_auto_confirm_taskand end the current processing task without assigningactive_focus_id. - If the user rejects during the countdown, consume the pending context and resume without focus state.
- Otherwise auto-confirm publishes
focus_mode_activatedand dispatches continuation with the active focus prompt. - The client encrypts the focus ID with the chat key, stores it locally, and sends
update_encrypted_active_focus_idfor server persistence.
Backend: Deactivation
AI-initiated: Clear cache, persist to Directus, create system message, restart without focus mode prompt.
Client-initiated (focus_mode_deactivate_handler.py): WebSocket message chat_focus_mode_deactivate with chat_id + focus_id. Handler clears cache, dispatches Celery task to clear Directus, sends ACK.
Frontend: Activation UI (FocusModeActivationEmbed.svelte)
Renders inline in chat as a compact card:
- Countdown phase (4 seconds): App icon, focus mode name, “Activate in N sec…” with progress bar. User can click card or press ESC to reject.
- Activated phase: Card shows “Focus activated” with green accent.
- Rejected phase: Card hidden.
focusModeRejectedevent dispatched.ActiveChat.sveltesends WebSocket deactivation + local system message.
Context menu (via ChatMessage.svelte): “Deactivate” -> WebSocket deactivation. “Details” -> deep-link to settings.
ESC handling: Global document.addEventListener('keydown') registered on mount, cleaned up on destroy.
Frontend: Renderer and Registry
FocusModeActivationRenderer.tsmounts the Svelte component, dispatches custom events- Registered as
focus-mode-activationinembed_renderers/index.ts - Embed type and attributes defined in
message_parsing/types.tsandembedParsing.ts
Cache & Persistence
encrypted_active_focus_idstored in chat’slist_item_datacache key viaCacheService- Persisted to
chatscollection in Directus (field already exists in schema) - Frontend syncs via phased sync handler
Edge Cases
- Focus mode IDs are encrypted with chat-specific key (zero-knowledge)
- Server validates focus mode ID against available modes before activation
- Focus mode prompt loaded at system prompt beginning with markers (lines ~682-696 in
main_processor.py)
Related Docs
- Function Calling – tool preselection and execution
- Message Processing – overall pipeline
- Focus Modes Overview – user-facing documentation