2025-12-12 16:56:46 +00:00
|
|
|
|
---
|
2026-01-30 03:15:10 +01:00
|
|
|
|
summary: "How OpenClaw presence entries are produced, merged, and displayed"
|
2025-12-12 16:56:46 +00:00
|
|
|
|
read_when:
|
|
|
|
|
|
- Debugging the Instances tab
|
|
|
|
|
|
- Investigating duplicate or stale instance rows
|
2025-12-12 23:29:57 +00:00
|
|
|
|
- Changing gateway WS connect or system-event beacons
|
2026-01-31 16:04:03 -05:00
|
|
|
|
title: "Presence"
|
2025-12-12 16:56:46 +00:00
|
|
|
|
---
|
2026-01-31 21:13:13 +09:00
|
|
|
|
|
2025-12-12 16:56:46 +00:00
|
|
|
|
# Presence
|
|
|
|
|
|
|
2026-01-30 03:15:10 +01:00
|
|
|
|
OpenClaw “presence” is a lightweight, best‑effort view of:
|
2026-01-31 21:13:13 +09:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- the **Gateway** itself, and
|
|
|
|
|
|
- **clients connected to the Gateway** (mac app, WebChat, CLI, etc.)
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
Presence is used primarily to render the macOS app’s **Instances** tab and to
|
|
|
|
|
|
provide quick operator visibility.
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## Presence fields (what shows up)
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
Presence entries are structured objects with fields like:
|
|
|
|
|
|
|
2026-01-12 04:55:31 +00:00
|
|
|
|
- `instanceId` (optional but strongly recommended): stable client identity (usually `connect.client.instanceId`)
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- `host`: human‑friendly host name
|
|
|
|
|
|
- `ip`: best‑effort IP address
|
2025-12-12 16:56:46 +00:00
|
|
|
|
- `version`: client version string
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- `deviceFamily` / `modelIdentifier`: hardware hints
|
2026-01-12 04:55:31 +00:00
|
|
|
|
- `mode`: `ui`, `webchat`, `cli`, `backend`, `probe`, `test`, `node`, ...
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- `lastInputSeconds`: “seconds since last user input” (if known)
|
|
|
|
|
|
- `reason`: `self`, `connect`, `node-connected`, `periodic`, ...
|
2025-12-12 16:56:46 +00:00
|
|
|
|
- `ts`: last update timestamp (ms since epoch)
|
|
|
|
|
|
|
|
|
|
|
|
## Producers (where presence comes from)
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
Presence entries are produced by multiple sources and **merged**.
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
|
|
|
|
|
### 1) Gateway self entry
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
The Gateway always seeds a “self” entry at startup so UIs show the gateway host
|
|
|
|
|
|
even before any clients connect.
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
### 2) WebSocket connect
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
Every WS client begins with a `connect` request. On successful handshake the
|
|
|
|
|
|
Gateway upserts a presence entry for that connection.
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
#### Why one‑off CLI commands don’t show up
|
2025-12-12 17:27:11 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
The CLI often connects for short, one‑off commands. To avoid spamming the
|
|
|
|
|
|
Instances list, `client.mode === "cli"` is **not** turned into a presence entry.
|
2025-12-12 17:27:11 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
### 3) `system-event` beacons
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
Clients can send richer periodic beacons via the `system-event` method. The mac
|
|
|
|
|
|
app uses this to report host name, IP, and `lastInputSeconds`.
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-22 22:02:00 +00:00
|
|
|
|
### 4) Node connects (role: node)
|
2026-01-31 21:13:13 +09:00
|
|
|
|
|
2026-01-22 22:02:00 +00:00
|
|
|
|
When a node connects over the Gateway WebSocket with `role: node`, the Gateway
|
|
|
|
|
|
upserts a presence entry for that node (same flow as other WS clients).
|
2026-01-04 14:30:43 +01:00
|
|
|
|
|
2025-12-12 16:56:46 +00:00
|
|
|
|
## Merge + dedupe rules (why `instanceId` matters)
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
Presence entries are stored in a single in‑memory map:
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- Entries are keyed by a **presence key**.
|
2026-01-12 04:55:31 +00:00
|
|
|
|
- The best key is a stable `instanceId` (from `connect.client.instanceId`) that survives restarts.
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- Keys are case‑insensitive.
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
If a client reconnects without a stable `instanceId`, it may show up as a
|
|
|
|
|
|
**duplicate** row.
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## TTL and bounded size
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
Presence is intentionally ephemeral:
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- **TTL:** entries older than 5 minutes are pruned
|
|
|
|
|
|
- **Max entries:** 200 (oldest dropped first)
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
This keeps the list fresh and avoids unbounded memory growth.
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
|
|
|
|
|
## Remote/tunnel caveat (loopback IPs)
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
When a client connects over an SSH tunnel / local port forward, the Gateway may
|
|
|
|
|
|
see the remote address as `127.0.0.1`. To avoid overwriting a good client‑reported
|
|
|
|
|
|
IP, loopback remote addresses are ignored.
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
## Consumers
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
|
|
|
|
|
### macOS Instances tab
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
The macOS app renders the output of `system-presence` and applies a small status
|
|
|
|
|
|
indicator (Active/Idle/Stale) based on the age of the last update.
|
2025-12-12 16:56:46 +00:00
|
|
|
|
|
|
|
|
|
|
## Debugging tips
|
|
|
|
|
|
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- To see the raw list, call `system-presence` against the Gateway.
|
2025-12-12 16:56:46 +00:00
|
|
|
|
- If you see duplicates:
|
2026-01-12 04:55:31 +00:00
|
|
|
|
- confirm clients send a stable `client.instanceId` in the handshake
|
2026-01-08 23:06:56 +01:00
|
|
|
|
- confirm periodic beacons use the same `instanceId`
|
|
|
|
|
|
- check whether the connection‑derived entry is missing `instanceId` (duplicates are expected)
|