Found during the delivery-path audit behind AgentWorkforce/relay#1273.
Problem
AgentClient.disconnect() / presence.markOffline() always send POST /v1/agents/disconnect (packages/sdk-typescript/src/agent.ts ~188–191, ~275–298 — "Always send the HTTP disconnect"). That presence-intent endpoint runs the full node teardown: routes/presence.ts ~47–65 → handleAgentDisconnect → deregisterAgentViaNode (src/engine/node.ts ~1144–1189), which deactivates the agent_node_bindings row, re-homes location_node_id to the implicit offline direct node (node_direct_<agentId>), and releases the node slot.
If any one-shot SDK/CLI/MCP usage of a broker-hosted agent's token ends with a disconnect (easy to do accidentally), the agent's broker routing is destroyed while its PTY keeps running on the node:
- Subsequent authenticated calls flip
status back to active via touchLastSeen, masking the damage.
- New deliveries snapshot
route_node_id = node_direct_<agentId> (src/engine/deliveryWrites.ts ~281–307) — an offline node — so they queue forever (see also the no-ws-redrive issue) while the agent can still send normally.
- Broker heartbeats never repair it; only a broker reconnect with
inventory.sync or a fresh agent.register re-binds.
Suggested fixes
- Make the SDK's disconnect presence-only for
via_node agents (or add an explicit opt-in for the full deregistration teardown).
- Alternatively, have the engine treat
/v1/agents/disconnect from a non-node credential as presence intent rather than deregisterAgentViaNode when an active node binding exists.
- Either way, log the re-homing at warn — today it's invisible.
Found during the delivery-path audit behind AgentWorkforce/relay#1273.
Problem
AgentClient.disconnect()/presence.markOffline()always sendPOST /v1/agents/disconnect(packages/sdk-typescript/src/agent.ts~188–191, ~275–298 — "Always send the HTTP disconnect"). That presence-intent endpoint runs the full node teardown:routes/presence.ts~47–65 →handleAgentDisconnect→deregisterAgentViaNode(src/engine/node.ts~1144–1189), which deactivates theagent_node_bindingsrow, re-homeslocation_node_idto the implicit offline direct node (node_direct_<agentId>), and releases the node slot.If any one-shot SDK/CLI/MCP usage of a broker-hosted agent's token ends with a disconnect (easy to do accidentally), the agent's broker routing is destroyed while its PTY keeps running on the node:
statusback toactiveviatouchLastSeen, masking the damage.route_node_id = node_direct_<agentId>(src/engine/deliveryWrites.ts~281–307) — an offline node — so they queue forever (see also the no-ws-redrive issue) while the agent can still send normally.inventory.syncor a freshagent.registerre-binds.Suggested fixes
via_nodeagents (or add an explicit opt-in for the full deregistration teardown)./v1/agents/disconnectfrom a non-node credential as presence intent rather thanderegisterAgentViaNodewhen an active node binding exists.