logo
Development
Search
Multi-Node Architecture

Multi-Node Architecture

Overview

The multi-node architecture enables multiple devices to work together, delivering a distributed experience of "chat on Device A, execute on Device B". The Gateway acts as the central dispatch hub, managing the registration, discovery, and intelligent routing of all nodes.


Architecture Overview

┌─────────┐ WebSocket ┌─────────────────┐ WebSocket ┌──────────┐ │ Web │ ◄───────────► │ Gateway │ ◄───────────► │APP Node A│ │(Browser)│ │ (Node.js) │ │ (macOS) │ └─────────┘ │ │ └──────────┘ │ - Node register│ │ - Smart routing│ ┌──────────┐ │ - Msg forward │ ◄───────────► │APP Node B│ │ - Auth verify │ │(Windows) │ └─────────────────┘ └──────────┘
                      
                      ┌─────────┐   WebSocket   ┌─────────────────┐   WebSocket   ┌──────────┐
│ Web     │ ◄───────────► │     Gateway     │ ◄───────────► │APP Node A│
│(Browser)│               │    (Node.js)    │               │ (macOS)  │
└─────────┘               │                 │               └──────────┘
                          │  - Node register│
                          │  - Smart routing│               ┌──────────┐
                          │  - Msg forward  │ ◄───────────► │APP Node B│
                          │  - Auth verify  │               │(Windows) │
                          └─────────────────┘               └──────────┘

                    
This code block in the floating window

Screenshot placeholder


Node Types

Type Identifier Description Execution Capability
Human Web browser Web-side user node No Agent Engine
Agent APP desktop Full Agent execution node Yes (local Sidecar)
Action Automation node Unattended execution Yes
Monitor Monitoring node Status monitoring No

Node Registration Information

When each node connects to the Gateway, it registers the following information:

Field Description
nodeId Unique node identifier
displayName Display name
platform Operating system (macOS / Windows / Linux / Browser)
version / coreVersion / uiVersion Version information
deviceFamily / modelIdentifier Device information
caps Capability string array
tools List of available tool descriptions
commands List of executable commands
description Node capability description text
scope Visibility scope (account / enterprise)

Node Visibility Scope

Scope Visibility Rule Description
account Visible only to the same userId Personal node, usable across organizations
enterprise Visible to all members of the same orgId Enterprise node, shared within the organization

account-level nodes: A user logged in on multiple devices can dispatch tasks between any of those devices.

enterprise-level nodes: Shared execution resources within an organization that all members can use via the Gateway.


Gateway Intelligent Routing

When a Web-side user initiates a conversation, the Gateway uses a three-tier fallback strategy to select the most suitable execution node:

Tier 1: LLM Semantic Routing

Uses the OpenAI API to analyze user intent and match the best node:

Input Description
User message The conversation content sent by the user
Node list Each node's name, description (up to 500 characters), and tool list (up to 15 items)

The LLM returns: {nodeId, confidence, reason}

Security measures:

  • Node descriptions are treated as DATA, not executed as instructions
  • Prevents prompt injection through node descriptions

Note: LLM routing currently has no model configured and will automatically fall back to Tier 2.

Tier 2: BM25 Keyword Matching

Performs keyword matching between the user query and node descriptions based on the BM25 algorithm:

Parameter Value
k1 1.5
b 0.75
Chinese support Character-level tokenization (\u4e00-\u9fff)

Returns the highest-scoring node, or null (no match).

Tier 3: Most Recent Connection Fallback

Selects the most recently connected node by the connectedAtMs timestamp, ensuring there is always a fallback result.


Remote Execution

Conversation Flow

1. The Web side sends chat.send to the Gateway 2. The Gateway performs intelligent routing and selects the target node 3. The Gateway forwards the message to the APP node 4. The APP node starts the Agent Loop to execute the task 5. Streaming events during execution are returned via chat.event 6. The Web side renders the execution process in real time
                      
                      1. The Web side sends chat.send to the Gateway
2. The Gateway performs intelligent routing and selects the target node
3. The Gateway forwards the message to the APP node
4. The APP node starts the Agent Loop to execute the task
5. Streaming events during execution are returned via chat.event
6. The Web side renders the execution process in real time

                    
This code block in the floating window

Remote Tool Invocation

1. The main Agent specifies the remote node via dispatch_multi_node_agent 2. The Gateway sends node.invoke.request to the target node 3. The remote node starts an independent Agent Loop 4. Upon completion, the result is returned via node.invoke.result
                      
                      1. The main Agent specifies the remote node via dispatch_multi_node_agent
2. The Gateway sends node.invoke.request to the target node
3. The remote node starts an independent Agent Loop
4. Upon completion, the result is returned via node.invoke.result

                    
This code block in the floating window

Attachment Hoisting (2026-04 update) NEW

During cross-node dispatch, if a message contains inline base64 attachments (images, documents, etc.), the system automatically uploads them to cloud storage and switches to URL references:

  • Reason: Avoids transmission failures caused by oversized Gateway RPC messages
  • Timing: Executed automatically before remote dispatch, transparent to the user
  • OS path normalization: Automatically converts path separators when dispatching across operating systems (macOS/Windows/Linux)

Permission Popup Distribution Rules

During cross-node execution, deciding "which side displays" the tool permission popup is a key product decision — it must strike a balance between "the user can respond promptly" and "preventing unauthorized triggering of sensitive operations".

Same-Account Scenarios (caller and executor are the same account)

Scenario Popup Location and Available Actions Status
node-A APP → node-B APP (same account logged in on both ends) The popup information is pushed to node-A via the Gateway; node-A displays the popup and can click "Allow / Always Allow" ⚠️ Cross-end distribution not yet implemented
node-C Web → node-B APP (same account, Web calling APP) The popup is displayed and responded to on node-C Web ✅ Implemented
IM channel messages (default target node initiated by the same account, DingTalk/Feishu/Telegram, etc.) If the channel supports form/button interaction, the permission popup is converted into that channel's interactive style (implemented via AskUserQuestion); when unsupported, it defaults to deny (without waiting 5 minutes) ✅ Implemented

Cross-Account Scenarios (enterprise node called across accounts)

  • node-D is an enterprise-type node (discoverable by other users within the same organization), currently logged in as user001
  • node-E (logged in as user002, either APP or Web) sends a message to node-D via the Gateway
  • If node-D requires tool permission during execution:
    • The popup is displayed only on node-D's local interface and is not distributed cross-end to node-E
    • Defaults to deny after 5 minutes with no response

Design Rationale

Rule Rationale
Same-account multi-end allows cross-end authorization The user can handle authorization requests on any end, avoiding tasks being blocked because a particular end is not at hand
Cross-account enterprise does not distribute cross-end Strictly restricted to the callee's local machine, preventing external accounts from triggering sensitive operations (such as local file read/write or Bash execution) via remote messages
Default to deny when the IM channel does not support interaction When the IM side cannot present a popup, prevents requests from hanging and blocking the Agent flow
Cross-account 5-minute timeout Balances "the user may have stepped away temporarily" against "avoiding tasks hanging for a long time"

Implementation reminder: The same-account cross-end distribution path for node-A APP → node-B APP currently does not exist. Requirements involving this path need a new Gateway route plus receiving/display logic on the APP side; do not assume it is already available.


Cross-Account Gateway Isolation NEW

Beyond the location rules for permission popups, data access itself is also isolated:

Personal Memory Isolation

When a node is called across accounts at enterprise scope:

  • Account-level memory (bound to userId): ❌ Not accessible
  • Enterprise-level memory (bound to orgId): ✅ Accessible
  • Session-level memory (this session): ✅ Accessible

The isRemoteSession flag enforces filtering during memory queries — a cross-account caller cannot read the personal memory of the target node's owner via memory_query.

Why It Is Designed This Way

  • Privacy protection: Your personal preferences, work habits, and account information cannot be read by a colleague through calling your node
  • Enterprise sharing: Organizational knowledge such as the tech stack and standards is still shared normally, without affecting collaboration
  • Compliance needs: Meets the "least privilege" requirements of privacy regulations such as GDPR

Conversation Icon Distinction

Conversations from different sources display different icons in the conversation list:

Icon Meaning
Computer icon (LocalComputerIcon) Initiated or executed by a local APP node
Server icon (NodeIcon) Executed by a remote node
Platform icon (Telegram/WeChat, etc.) From an IM channel

Determined based on the isLocalInitiated, targetNodeId, and sourceChannel fields.


WebSocket Protocol

Connection Handshake

1. Client → Gateway: connect.challenge 2. Gateway → Client: challenge (contains nonce) 3. Client → Gateway: connect (contains signed JWT) 4. Gateway → Client: hello-ok (confirms connection)
                      
                      1. Client → Gateway: connect.challenge
2. Gateway → Client: challenge (contains nonce)
3. Client → Gateway: connect (contains signed JWT)
4. Gateway → Client: hello-ok (confirms connection)

                    
This code block in the floating window

Heartbeat Keepalive

  • tick mechanism: Periodic heartbeats maintain the connection
  • Reconnection: Exponential backoff retry
  • Expiration cleanup: The Gateway periodically cleans up expired node sessions

Flow Control

  • Delta throttling: SSE streaming events are aggregated over 150ms to reduce the number of WebSocket frames
  • Run TTL: 10-minute timeout, with expired Runs cleaned up hourly

What This Means for You

The multi-node architecture lets you initiate tasks anywhere and have the most suitable device execute them.

Typical scenarios:

  • At a café, using your phone's browser (Web side) to initiate a task that requires access to files on your office computer → the Gateway automatically routes the task to your office's APP node for execution
  • A high-performance server in your team (macOS Pro) that keeps the APP running and is set to enterprise → all team members can dispatch heavy work to it from their own browsers

The experience you can feel:

  • When you initiate a conversation on the Web side, the system automatically selects an online APP node to execute it
  • The conversation list displays different icons so you know whether a conversation is executed locally or remotely
  • If no APP node is online, the Web side prompts that tasks requiring Agent capabilities cannot be executed
  • When the APP is installed on multiple computers, you can manually choose which computer to execute on

What you need to be aware of:

  • The Web side cannot execute Agent tasks independently; it requires at least one APP node to be online
  • Remotely executed conversations have network latency (depending on the network quality between the Gateway and the node)
  • When you set a node to enterprise scope, team members can dispatch tasks to your device — but your personal memory will not be accessed