Skip to content

sdk-typescript: unconditional HTTP disconnect re-homes a broker-hosted agent off its node, silently breaking delivery #272

Description

@willwashburn

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 → handleAgentDisconnectderegisterAgentViaNode (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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions