Problem
When a user removes themselves from a group using conversation remove-members <conversationId> <ownInboxId>, remaining members never receive a group_updated event. This means agents (and other members) can't detect that someone left, and can't determine if they're the last member in the group.
Removing a different member works correctly — remaining members see "Somebody removed Somebody" as a group_updated message.
Root Cause
remove-members always calls group.removeMembers(inboxIds) — the admin-removal path — even when the target is the caller's own inbox. The XMTP SDK has a separate self-removal API:
group.removeMembers([otherId]) — Admin removes someone else. Creates an MLS commit that propagates to all remaining members as group_updated. Works correctly.
conversation.leaveGroup() / requestRemoval() — Member requests to leave. Sets PendingRemove state. A PendingSelfRemoveWorker on another member's node processes the removal and creates the commit, so remaining members receive the group_updated.
When removeMembers() is called with your own inbox ID, you're the committer AND the removed party. The commit doesn't propagate to remaining members because the author is no longer in the group by the time it would be delivered.
Reproduction
# User A creates group, user B and agent join
convos conversations create --name "test" --env dev --json
# ... user B and agent join via invite ...
# User A removes user B — agent DOES see group_updated ✓
convos conversation remove-members <convId> <userBInboxId> --env dev
# User A removes themselves — agent sees NOTHING ✗
convos conversation remove-members <convId> <userAInboxId> --env dev
Confirmed with debug logging on the agent's XMTP bridge — zero events arrive after self-removal.
Suggested Fix
Either:
- Add a
conversation leave command that calls leaveGroup() / requestRemoval() for proper MLS self-removal
- Detect self-removal in
remove-members: if any of the target inbox IDs match the caller's inbox, use leaveGroup() instead of removeMembers() for that ID
Option 2 is more backwards-compatible — existing scripts using remove-members with their own ID would start working correctly.
Impact
Agents that rely on group_updated to detect "last member" status and self-destruct never fire when the last human removes themselves. This affects both the OpenClaw and Hermes runtimes.
Problem
When a user removes themselves from a group using
conversation remove-members <conversationId> <ownInboxId>, remaining members never receive agroup_updatedevent. This means agents (and other members) can't detect that someone left, and can't determine if they're the last member in the group.Removing a different member works correctly — remaining members see
"Somebody removed Somebody"as agroup_updatedmessage.Root Cause
remove-membersalways callsgroup.removeMembers(inboxIds)— the admin-removal path — even when the target is the caller's own inbox. The XMTP SDK has a separate self-removal API:group.removeMembers([otherId])— Admin removes someone else. Creates an MLS commit that propagates to all remaining members asgroup_updated. Works correctly.conversation.leaveGroup()/requestRemoval()— Member requests to leave. SetsPendingRemovestate. APendingSelfRemoveWorkeron another member's node processes the removal and creates the commit, so remaining members receive thegroup_updated.When
removeMembers()is called with your own inbox ID, you're the committer AND the removed party. The commit doesn't propagate to remaining members because the author is no longer in the group by the time it would be delivered.Reproduction
Confirmed with debug logging on the agent's XMTP bridge — zero events arrive after self-removal.
Suggested Fix
Either:
conversation leavecommand that callsleaveGroup()/requestRemoval()for proper MLS self-removalremove-members: if any of the target inbox IDs match the caller's inbox, useleaveGroup()instead ofremoveMembers()for that IDOption 2 is more backwards-compatible — existing scripts using
remove-memberswith their own ID would start working correctly.Impact
Agents that rely on
group_updatedto detect "last member" status and self-destruct never fire when the last human removes themselves. This affects both the OpenClaw and Hermes runtimes.