OpenClaw Windows Node Architecture: A Modular Four-Layer Desktop System
OpenClaw Windows Node implements a modular, layered desktop architecture that separates the WinUI tray interface from WebSocket connection management, credential persistence, and on-boarding logic to ensure testability and maintainability.
OpenClaw Windows Node is a Windows desktop application that provides a system-tray experience for connecting a user's local machine to an OpenClaw gateway. According to the source code in openclaw/openclaw-windows-node, the architecture cleanly divides responsibilities across four distinct layers, preventing direct UI-to-network coupling and enabling both headed and headless operation modes.
The Four Architectural Layers
The codebase organizes functionality into isolated tiers, each with explicit boundaries and public interfaces.
UI (Tray) Layer
The topmost layer presents the user-facing interface through WinUI 3 XAML pages and Windows system-tray integration. Key components include:
src/OpenClaw.Tray.WinUI/Pages/ConnectionPage.xaml– Displays connection status and gateway pairing UI.src/OpenClaw.Tray.WinUI/Services/NodeService.cs– A background service that keeps the node process alive independently of visible UI pages.src/OpenClaw.Tray.WinUI/App.xaml.cs– Application bootstrap that instantiates a singletonGatewayConnectionManagerand wires it to the NodeService.
UI pages never invoke the gateway client directly; they interact exclusively through the connection manager's immutable snapshot (GatewaySnapshot).
Connection Layer
This layer manages the lifecycle of the WebSocket connection to the gateway, handles pairing handshakes, and implements reconnection logic.
src/OpenClaw.Connection/GatewayConnectionManager.cs– The single owning object per process that opens the WebSocket, performs the device handshake, and stores tokens. It exposesEnsureNodeConnectedAsync()andDisconnectAsync()APIs.src/OpenClaw.Connection/IGatewayConnectionManager.cs– The public interface consumed by UI and service layers.src/OpenClaw.Connection/ChatNavigationReadiness.cs– Helper class that queries the manager to determine when the operator handshake is complete and chat UI can be shown.
The GatewayConnectionManager in src/OpenClaw.Connection/GatewayConnectionManager.cs follows a Single Owner Model, ensuring only one connection instance exists per process to prevent duplicate sockets and state fragmentation.
Credential & Registry Layer
Responsible for persisting gateway credentials and abstracting migration logic from legacy formats.
src/OpenClaw.Shared/GatewayRegistry.cs– The newer API that all writes traverse; reads from%APPDATA%\OpenClawTray\gateways.jsonand per-gateway identity files.src/OpenClaw.Shared/Settings/SettingsManager.cs– Legacy settings reader/writer used only for one-time migration scenarios.
Credential storage follows a strict Token Precedence hierarchy: device token takes priority over shared gateway token, which takes priority over bootstrap token. The system never downgrades a paired device back to bootstrap credentials.
Setup / On-boarding Layer
Guides new installations through pairing, QR code scanning, and initial configuration generation.
src/OpenClaw.SetupEngine/SetupWizardRunner.cs– Orchestrates the wizard steps defined inSetupPipeline.csandSetupContext.cs.src/OpenClaw.SetupEngine.UI– XAML views for the on-boarding flow (welcome, permissions, progress).src/OpenClaw.SetupEngine/TrayArtifactCleanup.cs– Removes stale tray artifacts after successful setup.
The SetupEngine is a pure-C# pipeline executable in both interactive UI mode and headless CLI mode.
CLI Layer (Optional)
Provides a command-line entry point for scripting or automation scenarios.
src/OpenClaw.WinNode.Cli/Program.cs– Parses arguments and runs the node without WinUI, utilizing the sameGatewayConnectionManagerandGatewayRegistryservices as the tray application.
Layer Interaction Lifecycle
Understanding how these layers interact reveals the system's startup and operational flow.
- Startup –
App.xaml.cscreates the singletonGatewayConnectionManagerand registers it withNodeService. - Credential Load –
GatewayRegistryattempts to read%APPDATA%\OpenClawTray\gateways.json. If no gateway exists, the SetupEngine launches the on-boarding wizard. - Pairing –
GatewayConnectionManageropens a WebSocket to the gateway URL, negotiates the handshake, and persists the resulting device token via the registry. - Operation – UI pages like
ChatPage.xamlandChannelsPage.xamlsubscribe to connection events exposed by the manager, sending and receiving messages through its API. - Reconnection – Upon WebSocket failure, the manager automatically reattempts connection using the stored token hierarchy without UI intervention.
Key Architectural Concepts
The design enforces several invariants that simplify testing and extension.
Single Owner Model – Only one GatewayConnectionManager instance exists per process. This prevents race conditions in connection state and provides a unified source of truth for the UI.
Decoupled UI – View logic depends solely on the IGatewayConnectionManager interface and immutable snapshots. The UI layer has no reference to WebSocket implementations or network protocols.
Isolation for Tests – The test suite replaces SettingsManager with a temporary directory specified by the OPENCLAW_TRAY_DATA_DIR environment variable, ensuring unit tests never touch real user data in %APPDATA%.
Modular On-boarding – The SetupEngine pipeline in src/OpenClaw.SetupEngine can execute headlessly or with full WinUI visuals, making it reusable across the tray app and CLI tool.
Practical Code Examples
Below are typical interactions with the core architecture.
Creating and connecting via the manager:
// Bootstrap (normally in App.xaml.cs)
var manager = new GatewayConnectionManager(
resolver: new GatewayUrlResolver(),
factory: new WebSocketFactory(),
registry: new GatewayRegistry(),
logger: NullLogger.Instance);
// Connect from UI or service
await manager.EnsureNodeConnectedAsync(CancellationToken.None);
// Query state for data binding
var snapshot = manager.CurrentSnapshot;
bool isConnected = snapshot.IsConnected;
bool chatReady = ChatNavigationReadiness.IsOperatorHandshakeReady(manager);
Running the on-boarding wizard programmatically:
var wizard = new SetupWizardRunner(
pipeline: new SetupPipeline(),
logger: NullLogger.Instance);
await wizard.RunAsync(CancellationToken.None);
Reading persisted credentials:
var registry = new GatewayRegistry(); // reads %APPDATA%\OpenClawTray\gateways.json
var gateway = registry.GetGatewayById("my-gateway-id");
string deviceToken = gateway?.DeviceToken;
Summary
- OpenClaw Windows Node uses a four-layer architecture (UI, Connection, Credential, Setup) to isolate concerns.
GatewayConnectionManagerinsrc/OpenClaw.Connection/GatewayConnectionManager.csis the sole owner of WebSocket lifecycle and enforces single-instance semantics.- Credentials follow a strict precedence (device → shared → bootstrap) and persist to
%APPDATA%\OpenClawTray\viaGatewayRegistry. - The SetupEngine supports both GUI and CLI execution modes, defined in
src/OpenClaw.SetupEngine/SetupWizardRunner.cs. - UI decoupling is achieved through immutable snapshots and the
IGatewayConnectionManagerinterface, enabling comprehensive test isolation.
Frequently Asked Questions
How does OpenClaw Windows Node handle connection reconnection?
The GatewayConnectionManager continuously monitors the underlying WebSocket. Upon detecting a failure, it automatically triggers EnsureNodeConnectedAsync, which attempts reconnection using the stored token hierarchy without requiring user interaction. As implemented in src/OpenClaw.Connection/GatewayConnectionManager.cs, this process respects the token precedence—device tokens are preferred over shared or bootstrap tokens—and persists new credentials through GatewayRegistry upon successful re-handshake.
Where are gateway credentials stored on disk?
Gateway credentials are persisted as JSON files under %APPDATA%\OpenClawTray\. The GatewayRegistry class in src/OpenClaw.Shared/GatewayRegistry.cs manages reading and writing to gateways.json and individual gateway identity files. Legacy migration logic from older versions is handled by SettingsManager in src/OpenClaw.Shared/Settings/SettingsManager.cs, but all new writes flow exclusively through the GatewayRegistry API.
Can the application run without the WinUI interface?
Yes. The src/OpenClaw.WinNode.Cli/Program.cs entry point provides a headless mode that parses command-line arguments and executes the GatewayConnectionManager and SetupEngine without loading any XAML pages. This CLI layer uses identical services to the tray application, ensuring consistent behavior across interactive and automated deployment scenarios.
What prevents multiple simultaneous connections to the same gateway?
The Single Owner Model enforced by GatewayConnectionManager ensures only one instance exists per process. The application bootstrap in App.xaml.cs creates this as a singleton and injects it into NodeService and UI pages. This architectural constraint prevents duplicate WebSocket connections and eliminates state fragmentation between competing connection managers.
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 →