Skip to content

deleteSubAgent doesn't stick while a client is still connected #2003

Description

@MiguelsPizza

Steps:

  1. A client opens a WebSocket to a sub-agent (a /sub/... path through the parent).
  2. The parent calls deleteSubAgent for that sub-agent. hasSubAgent now returns false.
  3. The client sends one more message, or just disconnects.
  4. hasSubAgent returns true again. The sub-agent is back, with fresh state.

Expected: the sub-agent stays deleted.

Cause: the parent routes every incoming WebSocket frame with _cf_resolveSubAgent, which creates the sub-agent when it doesn't exist. deleteSubAgent doesn't close open connections. So the old connection survives the delete, and its next message (or its close event) recreates the sub-agent it was pointing at.

Repro on main (a68736f), using the existing test agents:

const parent = await getAgentByName(env.TestSubAgentParent, parentName);
await parent.subAgentPing(childName);
const ws = await connectWS(
  `/agents/test-sub-agent-parent/${parentName}/sub/counter-sub-agent/${childName}`
);

await parent.subAgentDelete(childName);
expect(await parent.has("CounterSubAgent", childName)).toBe(false);

ws.send("straggler"); // or just ws.close()
await expect.poll(() => parent.has("CounterSubAgent", childName)).toBe(true);

Workaround: in _cf_forwardSubAgentWebSocketMessage and _cf_forwardSubAgentWebSocketClose, check hasSubAgent first and drop the frame when the sub-agent is gone.

Metadata

Metadata

Assignees

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