OpenClaw presence
How the Gateway’s live roster of clients is produced, merged, filtered and expired
Which clients are connected to my Gateway right now, from where, and doing what? OpenClaw answers that with presence: a lightweight, best-effort view of the Gateway itself and of the user-visible clients connected to it, the macOS app, WebChat, nodes and the rest, rendered on the Control UI devices page and the macOS instances tab. Here are the fields an entry carries, who can read the roster, where entries come from, how they are merged, when they expire, and the debugging tips for duplicate rows.
What an entry carries
- A stable instance id, strongly recommended, a human-friendly host name, the client type separate from its display name, a best-effort IP that the geolocation plugin can resolve to a coarse city, a version string, hardware hints, and a self-reported IANA time zone that stays useful when the IP is loopback, tunnelled or behind carrier NAT.
- A mode among ui, webchat, cli, backend, node, probe and test, seconds since last user input when known, a free-form reason where the Gateway itself only emits self, connect and disconnect, and the device id, roles and scopes from the connect handshake.
- A last-update timestamp that includes heartbeat updates and is not a user-activity timestamp, the start of the authenticated person’s current continuous online period shared across overlapping connections, and the latest observed accepted interaction, absent until activity is seen.
- The session keys the client explicitly declares it is viewing, filtered for each recipient.
The Gateway always seeds a \"self\" entry at startup so UIs show the gateway host even before any clients connect.
Who sees it
The roster is shared with operators holding operator read access, and write or admin access grants read as well. Readers can see other people’s online and activity timing and reported time zone, including people not watching any session; node connections, pairing-only operators and other connections without read access receive an empty roster in the connect snapshot and no presence events, and the system-presence call requires the same access. Watched-session references are filtered separately for each recipient using the same visibility rules as the session list: hidden or missing sessions are omitted entirely without counts or placeholders, drafts, incognito sessions and operator role restrictions follow those rules, deleted references are omitted even for admins, and being viewed does not grant the viewer access to a session. Message subscriptions alone do not declare viewer presence. The docs are explicit that this policy does not isolate all Gateway metadata, and that separate Gateway trust boundaries are the answer when readers must not see each other.
Producers and merging
- Four producers, merged: the Gateway self entry seeded at startup, the WebSocket connect handshake that upserts an entry per accepted connection, richer periodic system-event beacons that the macOS app uses for host name, IP, version and liveness, and node connects with the node role. Clients in cli, backend or probe mode are deliberately not turned into entries so that brief control-plane connections do not linger for the full TTL; test-mode clients stay tracked because suites use them as stand-ins.
- Entries live in one in-memory map with case-insensitive keys: user WebSocket clients get one row per connection so two tabs cannot overwrite each other, nodes key by device id, then instance id, then connection id, and beacons merge by device or instance id when supplied and otherwise by parsed host; a stable instance id helps consumers associate rows but never merges separate user connections. The Control UI groups rows by their recorded identity namespace, so connections sharing a qualified profile identity form one person while unqualified connections with the same raw id form a separate group.
- Presence is intentionally ephemeral: entries older than five minutes are pruned and the map holds at most two hundred, oldest dropped first. Over an SSH tunnel the Gateway may see the client as loopback, so connect handling omits the IP for detected-local clients rather than recording the tunnel address.
OpenClaw multi-user setups explains the people cards that keep online duration apart from heartbeat freshness, and OpenClaw nodes, remote hands the connections that appear here with the node role.
Debugging duplicates
The devices page joins the presence roster with durable pairing and node records, pins the Gateway self beacon first and uses matching device or instance ids for live platform, version, model and input-recency metadata, while the macOS app marks each instance active, idle or stale by the age of its last update. To see the list projected for your own connection, call system-presence against the Gateway; for duplicates, confirm clients send a stable instance id in the handshake, confirm beacons reuse it, and remember that separate user connections have separate rows that expire after the TTL. The OpenClaw Gateway explained is the process that keeps the map, and OpenClaw sessions the keys a watched-session reference points at.
On Diali
On Diali the roster lives inside your assistant’s Gateway like everywhere else: its own self entry, the browser tabs you open on the Control UI, and any computer you paired as a node, with rows ageing out five minutes after their last update. Hosted OpenClaw on Diali is the assistant and Diali security describes who can reach that Gateway at all.
- Best-effort, in memory, five minutes, two hundred rows.
- One row per user connection; CLI and probes never appear.
- Watched sessions are filtered per reader.
Stop reading about it, build one
Set up an agent, pick a channel, and have it working inside the app you already keep open.
