Skip to content

fix(octo): ignore bot's own echoes and non-conversation channels inbound#31

Merged
lml2468 merged 1 commit into
mainfrom
fix/octo-ignore-self-and-system-messages
Jun 12, 2026
Merged

fix(octo): ignore bot's own echoes and non-conversation channels inbound#31
lml2468 merged 1 commit into
mainfrom
fix/octo-ignore-self-and-system-messages

Conversation

@lml2468

@lml2468 lml2468 commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Problem (found while completing a real Octo binding)

The inbound hub dispatched two kinds of traffic that aren't user messages, each producing a bogus needs_binding outcome and a failed binding-prompt send (the not_friend / missing sender uid errors in the logs):

  1. The bot's own messages echo back on its own socket (from_uid == robot_id). Every agent reply looped back in as a new "unbound user" message; the replier then tried to DM the binding link to the bot itselferr.server.bot_api.not_friend.
  2. System/command channels. Octo emits e.g. channel_type 8 systemcmdonline on connect (empty from_uid); these slipped past the DM/group-mention gate and got an unsolicited "please bind" reply → missing sender uid.

Both are confirmed against the reference channel implementation (cc-channel-octo processMessage), which filters from_uid === robotId and gates on a supported channel type — guards we were missing.

Fix

In hub.onMessage, before any dedup / dispatch / audit work:

  • drop messages where from_uid == inst.RobotID (self-echo / reply loop);
  • drop any channel type that isn't a real conversation (DM / group / topic) via new isConversationChannel.

Both are dropped silently — they're not user traffic, so no audit row, no dedup churn, no spurious binding prompt. Real user DMs (from_uid = the human uid, type DM) are unaffected and still dispatch.

Verification

  • End-to-end: a bound owner's real DMs already create a chat session and receive agent replies (the octo_chat_session_binding + assistant messages exist) — unaffected by this change.
  • TestHub_IgnoresSelfAndSystemMessages: self (from_uid==robot) and a type-8 system message are dropped (no Handle, no replier), while a real DM is dispatched.
  • TestIsConversationChannel: DM/group/topic supported; type 8 / 0 rejected.

go vet + go test -race on the octo package clean.

Related observation (not in this PR): the reference also drops streamOn partial messages; our inbound doesn't process partials problematically today, but it's a candidate follow-up.

Discovered while debugging a real binding: the inbound hub dispatched two
kinds of traffic that aren't user messages, each producing a bogus
'needs binding' outcome and a failed binding-prompt send:

1. The bot's own outbound messages echo back on its socket (from_uid ==
   robot id). Every agent reply looped in as a new unbound-user message;
   the replier then tried to DM the binding link to the bot itself →
   'not_friend'. The reference channel filters from_uid == robotId in
   processMessage; we did not.
2. Octo emits system/command channels (channel_type 8 'systemcmdonline'
   on connect, empty from_uid) that slip past the group-mention gate and
   got an unsolicited prompt → 'missing sender uid'.

Fix: in hub.onMessage, before any dedup/dispatch/audit, drop messages
where from_uid == inst.RobotID, and drop any channel type that isn't a
real conversation (DM / group / topic) via isConversationChannel. Both
dropped silently — not user traffic, so no audit row or dedup churn.

Real user DMs still dispatch (verified end to end).

Tests: TestHub_IgnoresSelfAndSystemMessages + TestIsConversationChannel.
vet + -race clean.
@lml2468 lml2468 merged commit 6d558ff into main Jun 12, 2026
4 checks passed
@lml2468 lml2468 deleted the fix/octo-ignore-self-and-system-messages branch June 12, 2026 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant