Skip to content

[Bug]: MsgContext.canonicalKey() is not injective — distinct conversations can collapse to one gateway session key #3534

Description

@hermanrous

Description

io.agentscope.harness.agent.gateway.MsgContext#canonicalKey() joins the routing components with a bare | separator and does not escape that separator inside the components, so the key is not injective: two different routing contexts can produce the same canonical key.

new MsgContext("chatui", "team|r:room-1", null, null, null, Map.of()).canonicalKey();
// "chatui|g:team|r:room-1"
new MsgContext("chatui", "team", "room-1", null, null, Map.of()).canonicalKey();
// "chatui|g:team|r:room-1"   <-- same key, different conversation

extra keys and values are joined the same way, so a value may also forge structural fragments.

Impact

canonicalKey() is the gateway session key (session id derivation, per-key turn gate, session -> key wake-up map). A collision routes two distinct conversations to the same gateway session, so participants of one group/room can see the other's conversation state.

Reproduction

MsgContext groupOnly = new MsgContext("chatui", "team|r:room-1", null, null, null, Map.of());
MsgContext groupRoom = new MsgContext("chatui", "team", "room-1", null, null, Map.of());
assertNotEquals(groupOnly.canonicalKey(), groupRoom.canonicalKey());
// fails on main: expected: not equal but was: <chatui|g:team|r:room-1>

Proposed fix

Escape % (first) and | in every component before appending. Keys without reserved characters are unchanged, so existing session mappings are preserved.

I can open a PR for this if it looks reasonable.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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