#10407: fix(feishu): Remove incorrect oc_ prefix assumption in resolveFeishuSession
stale
Cluster:
Feishu Messaging Fixes
# Fix Feishu `oc_` prefix assumption causing DM misrouting
## ๐ Problem
`resolveFeishuSession` incorrectly assumes all `oc_` prefixed IDs are group chats. However, Feishu's `oc_` is a generic **chat_id** that can represent both groups **and** DMs (p2p chats).
## ๐ Impact
- DMs with `oc_` chat_ids are misrouted as group sessions
- Creates duplicate/incorrect session keys
- Breaks session isolation between DMs and groups
## ๐ Evidence
Verified with Feishu API queries:
| Chat ID | Actual Type (from API) | Current Behavior | Expected |
|---------|------------------------|------------------|----------|
| `oc_19dd...` | `chat_mode: "p2p"` (DM) | โ Treated as group | โ
Treat as DM |
| `oc_724b...` | `chat_mode: "group"` | โ
Treated as group | โ
Treat as group |
**Root cause:** The code incorrectly assumes ID prefix determines type, but Feishu uses the same `oc_` prefix for both groups and DMs.
## ๐ Solution
**Before:**
```javascript
const idLower = trimmed.toLowerCase();
if (idLower.startsWith("oc_")) isGroup = true; // โ Wrong assumption
else if (idLower.startsWith("ou_") || idLower.startsWith("on_")) isGroup = false;
```
**After:**
```javascript
let typeExplicit = false;
// Track if type was explicitly specified via prefix
if (lower.startsWith("group:") || lower.startsWith("chat:")) {
typeExplicit = true;
isGroup = true;
} else if (lower.startsWith("user:") || lower.startsWith("dm:")) {
typeExplicit = true;
isGroup = false;
}
// Only infer type from ID prefix if not explicitly specified
// Note: oc_ is a chat_id and can be either group or DM
// Only ou_/on_ can be reliably identified as user IDs (always DM)
if (!typeExplicit) {
if (idLower.startsWith("ou_") || idLower.startsWith("on_")) {
isGroup = false;
}
// oc_ requires explicit prefix: dm:oc_xxx or group:oc_xxx
}
```
**Key changes:**
1. โ
Add `typeExplicit` flag to track explicit type specification
2. โ
Remove incorrect `oc_` โ group assumption
3. โ
Keep `ou_`/`on_` โ DM inference (these are user IDs, always DM)
4. โ
`oc_` IDs now require explicit `dm:` or `group:` prefix
## โ
Testing
Tested with real Feishu environment:
- [x] DM with `oc_` chat_id correctly routes to DM session
- [x] Group with `oc_` chat_id correctly routes to group session
- [x] Explicit prefixes (`dm:oc_xxx`, `group:oc_xxx`) work correctly
- [x] User IDs (`ou_`, `on_`) still infer as DM
- [x] No regression on existing group chats
## ๐ Context
Feishu's ID format:
- **`oc_`**: chat_id (generic, can be group or DM - **needs `chat_mode` to distinguish**)
- **`ou_`**: user open_id (always DM)
- **`on_`**: user union_id (always DM)
The correct approach is to either:
1. Use `chat_mode` field from Feishu API response (for incoming messages) โ
2. Require explicit type prefix for outgoing messages (`dm:` or `group:`) โ
This PR implements approach #2 for `resolveFeishuSession` (outbound routing).
## โ ๏ธ Limitation
Bare `oc_` without an explicit prefix now defaults to DM (`isGroup=false`).
This is a safer default than the previous behavior (always group), as
misrouting a group message to a DM session has a smaller blast radius
than the reverse โ a DM session leaking into a group context is a worse
outcome from both a privacy and UX perspective.
For outbound routing (e.g. message tool, cron delivery), callers should
use explicit prefixes: `group:oc_xxx` or `dm:oc_xxx`.
## ๐ฎ Future improvement
Auto-detection of `oc_` chat type (e.g. via session store lookup or
Feishu Chat API query) could eliminate the need for explicit prefixes
entirely. This is out of scope for this fix but tracked in #12658.
## ๐ Related
- Feishu Open Platform Docs: https://open.feishu.cn/document/home/user-identity-introduction/introduction
- Follow-up: #12658 (auto-detect oc_ chat type)
---
**First-time contributor here!** ๐ Found this bug while using OpenClaw's Feishu integration and verified with API calls. Happy to make any adjustments based on feedback.
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
- Updates Feishu outbound target parsing to stop assuming all `oc_` IDs are group chats.
- Adds a `typeExplicit` flag so `group:`/`chat:` vs `dm:`/`user:` prefixes take precedence over ID-prefix heuristics.
- Keeps `ou_`/`on_` inference as DM-only when no explicit type is provided, avoiding DM/group session key collisions for Feishu chat_ids.
<h3>Confidence Score: 4/5</h3>
- This PR is largely safe to merge, with one documentation inconsistency to fix.
- The logic change is small and localized to Feishu outbound session resolution, and it removes an incorrect inference that caused real misrouting. The main remaining issue is that the in-file Feishu ID format comment contradicts the new behavior and Feishu semantics, which can cause future regressions if left uncorrected.
- src/infra/outbound/outbound-session.ts
<!-- greptile_other_comments_section -->
<sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#10309: fix: use group ID for peer.id in Feishu group messages
by ParsifalC ยท 2026-02-06
83.2%
#13211: feat(feishu): skip reply-to in DM conversations
by Vincentwei1021 ยท 2026-02-10
78.4%
#9253: Fix: Feishu chat ID mismatch causing session context confusion
by vishaltandale00 ยท 2026-02-05
78.3%
#19793: feat(feishu): reply-in-thread, parallel group sessions, and fire-an...
by yinsn ยท 2026-02-18
78.3%
#21484: fix(feishu): scope message deduplication by accountId to support mu...
by guanyu-zhang ยท 2026-02-20
77.4%
#19027: fix(feishu): keep chunked messages in topic/thread context
by qiangu ยท 2026-02-17
75.1%
#21576: fix(feishu): stop ghost messages from corrupting active conversatio...
by xuanyue202 ยท 2026-02-20
74.4%
#17798: feat(feishu): support sender/topic-scoped group session routing
by yfge ยท 2026-02-16
73.4%
#22675: feishu: move message dedup to just before dispatch
by zijiegeng ยท 2026-02-21
72.6%
#19254: fix(feishu): honor wildcard group config for reply policy
by WaynePika ยท 2026-02-17
71.8%