fix(inbound): route fabric DM channels as peer.kind=direct / ChatType=direct #6
Reference in New Issue
Block a user
Delete Branch "fix/fabric-dm-routing-by-xtype"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Inbound was hardcoding
peer: { kind: 'group' }andChatType: 'group'for every fabric channel regardless of xType. Consequences:agent:<id>:fabric:group:<chan>instead ofagent:<id>:fabric:direct:<chan>ctx.ChatType='group'caused the user-prompt metadata to renderis_group_chat: trueon a DMisDirectMessage()check (ChatType==='direct') returned false, so DM-specific prompt and turn behavior never engagedThis was caught by the recruiter sim test in session
40c51de2-14f5-47fc-ad22-da9ebee5c4a8: the model's thinking trace acknowledged "fabric DM channel" (from the ClawPrompts chat-injector hook) but the surrounding user-prompt metadata contradicted it withis_group_chat: true, and the model reasoned its way out of runningworkflow_start.Approach
Small helper in
channel.ts:m.xTypedirectly (live, authoritative).resolveFabricOutboundSessionRoute) has no xType in its call signature, so it consults the channel-meta cache populated by inbound — samegetChannelTypealready exposed via__fabric. Cache miss falls back to'group', i.e. the pre-fix default — no regression on cold cache.Edge case left as-is: proactive DM to a channel with no prior inbound. That one outbound still routes as
'group'; the next inbound + outbound pair agrees on'direct'. Fixable later by warming the cache via fabric channel-list discovery if it becomes a real problem.Companion PR on the prompt side:
hzhang/ClawPrompts#3 hardens the chat-injector wording so the model doesn't bypassworkflow_startwhen the signals actually do align.Will sim-test both together before merging either.
Inbound was hardcoding `peer: { kind: 'group' }` and `ChatType: 'group'` for every fabric channel regardless of xType. As a result: - sessionKey for a DM was `agent:<id>:fabric:group:<chan>` instead of `agent:<id>:fabric:direct:<chan>` - ctx.ChatType='group' caused user-prompt metadata to render `is_group_chat: true` on a DM - openclaw's `isDirectMessage()` check (ChatType==='direct') returned false, so DM-specific prompt and turn behavior never engaged Caught by recruiter test in session 40c51de2: the model's thinking trace acknowledged "fabric DM channel" (from the ClawPrompts chat-injector hook) but the surrounding user-prompt metadata contradicted it with `is_group_chat: true`, and the model reasoned its way out of running `workflow_start`. Fix factors a small helper `fabricPeerRoutingForXType` (and a cache- backed `fabricPeerRoutingForChannel` for outbound) in channel.ts that maps: - 'dm' → { peerKind: 'direct', chatType: 'direct' } - rest → { peerKind: 'group', chatType: 'group' } (no change) Inbound uses m.xType directly (live, authoritative). Outbound has no xType in its call signature, so it consults the channel-meta cache populated by inbound (same `getChannelType` already exposed via __fabric). Cache miss falls back to 'group' — the pre-fix default, no regression. The proactive-DM-without-prior-inbound edge case still routes that one outbound as 'group'; the next round agrees on 'direct'. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>