Discord Thread Metadata Bloat and CLI Session Misrouting
Live Discord threads suffer from volatile metadata re-injection every turn and CLI agent commands resolve to the wrong session instead of the actual thread-bound session.
π Symptoms
Context Degradation in Long Discord Threads
Long-running Discord threads exhibit progressive performance decline and context quality degradation. Each conversational turn appends redundant metadata to the context window.
Before Fix β Repeated Metadata in Context:
[System] Loading conversation for thread: general-discussion
[Context] message_id: 1234567890
[Context] reply_to_id: 9876543210
[Context] timestamp: 2026-03-11T14:30:00Z
[Context] Thread starter: [email protected]
[Context] Chat history since last reply: 15 messages
---
[TURN 2]
[System] Loading conversation for thread: general-discussion
[Context] message_id: 1234567891
[Context] reply_to_id: 1234567890
[Context] timestamp: 2026-03-11T14:30:15Z
[Context] Thread starter: [email protected] β REPEATED
[Context] Chat history since last reply: 16 messages β REPEATED
---
[TURN N]
[Context] Thread starter: [email protected] β REPEATED N times
[Context] Chat history since last reply: N+15 messages β REPEATED N times
CLI Agent Command Landing in Wrong Session
Commands issued via CLI resolve to agent:*:main instead of the intended thread-specific session:
$ openclaw agent --channel discord --to 1487654321 send "status check"
[INFO] Sending to channel: discord
[INFO] Resolved session: agent:*:main β WRONG SESSION
[INFO] Message delivered to: #general-discussion (main session)
# Expected: agent:discord:1487654321
# Actual: agent:*:main (default fallback)
Runtime Behavior Observation
Post-restart of openclaw-gateway.service, sessions correctly resolve:
$ openclaw agent --channel discord --to 1487654321 send "status check"
[INFO] Sending to channel: discord
[INFO] Resolved session: agent:discord:1487654321 β CORRECT
[INFO] Message delivered to: thread-1487654321
π§ Root Cause
Issue 1: Volatile Metadata Re-injection in Discord Threads
Architectural Failure:
The runtime bundle dist/pi-embedded-D6PpOsxP.js contained a conditional check that treated Discord threads as requiring volatile metadata injection on every turn. The logic failed to differentiate between:
- New sessions: Require full metadata initialization
- Existing thread continuations: Should only carry forward the thread identifier, not re-inject ephemeral fields
The five fields being incorrectly re-injected:
| Field | Type | Injection Behavior |
|---|---|---|
message_id | Ephemeral | Regenerated per message |
reply_to_id | Ephemeral | Derived from parent reference |
timestamp | Ephemeral | Point-in-time value |
Thread starter | Session-level | Static, set once at thread creation |
Chat history since last reply | Derived | Computed on-demand, not stored |
Root Cause Chain:
Runtime bundle (pi-embedded) checks session type β Discord threads bypass ephemeral field optimization β Fields marked as volatile get re-injected every turn β Context window accumulates duplicate metadata β Progressive degradation and token bloat
Issue 2: CLI Session Resolution Failure
Architectural Failure:
The session resolver in dist/gateway-cli-BjsM6fWb.js and dist/compact-1mmJ_KWL.js lacked delivery context awareness. The resolution logic:
- Received
channelandtoparameters - Did not normalize Discord-specific target formats (
148...vschannel:148...) - Defaulted to
agent:*:mainwhen resolution context was insufficient - Did not correlate
replyAccount/accountIdfrom the delivery context
Root Cause Chain:
CLI command: openclaw agent –channel discord –to 1487654321 β Command path passes insufficient context to resolver β Resolver receives: { channel: “discord”, to: “1487654321” } β Normalization step missing target format handler β Key building uses wrong session template β Resolves to: agent:*:main (fallback default) β Message delivered to wrong session
Compound Regression from First Patch
The initial fix for Issue 1 introduced a secondary bug. In dist/register.agent-DHoJWl4M.js, the function resolveAgentMainSessionKey was incorrectly used where buildAgentMainSessionKey(...) was required. This caused the registration path to attempt resolving instead of building, further destabilizing session tracking.
π οΈ Step-by-Step Fix
Overview
Since the issue resides in compiled runtime bundles in openclaw/dist/, the fix requires direct patch application to these files. Note: These changes will be lost on reinstallation or update.
Phase 1: Patch pi-embedded-D6PpOsxP.js β Prevent Metadata Re-injection
File: openclaw/dist/pi-embedded-D6PpOsxP.js
Objective: Exclude Discord threads from volatile metadata re-injection for the specified fields.
Before:
javascript // Lines ~XXX: Volatile metadata injection const injectVolatile = (session, message) => { if (isEphemeralField(‘message_id’)) { /* inject / } if (isEphemeralField(‘reply_to_id’)) { / inject / } if (isEphemeralField(’timestamp’)) { / inject / } if (isEphemeralField(‘Thread starter’)) { / inject / } if (isEphemeralField(‘Chat history since last reply’)) { / inject */ }
// No Discord thread check here };
After:
javascript const injectVolatile = (session, message) => { // Skip re-injection for Discord threads (context persists across turns) if (session.channel === ‘discord’ && session.threadId) { return; // Preserve existing context, only update thread marker }
if (isEphemeralField(‘message_id’)) { /* inject / } if (isEphemeralField(‘reply_to_id’)) { / inject / } if (isEphemeralField(’timestamp’)) { / inject / } if (isEphemeralField(‘Thread starter’)) { / inject / } if (isEphemeralField(‘Chat history since last reply’)) { / inject */ } };
Phase 2: Patch gateway-cli-BjsM6fWb.js β Add Delivery Context Normalization
File: openclaw/dist/gateway-cli-BjsM6fWb.js
Objective: Normalize Discord target formats and resolve by actual delivery context.
Before (session resolution):
javascript
const resolveSession = (params) => {
const { channel, to } = params;
// Direct mapping, no normalization
const key = agent:${channel}:main;
return lookupSession(key);
};
After:
javascript const resolveSession = (params) => { const { channel, to } = params;
// Normalize Discord targets: “148…” β “channel:148…” const normalizedTo = normalizeDiscordTarget(to);
// Resolve by actual delivery context
const key = agent:${channel}:${normalizedTo};
return lookupSession(key, {
accountId: params.replyAccount || params.accountId
});
};
function normalizeDiscordTarget(target) { if (!target) return ‘main’; // Handle both “148…” and “channel:148…” formats if (target.startsWith(‘channel:’)) { return target.split(’:’)[1]; } // If purely numeric, it’s a Discord channel/thread ID if (/^\d+$/.test(target)) { return target; } return target; // passthrough for named targets }
Phase 3: Patch compact-1mmJ_KWL.js β Add Delivery Context Lookup
File: openclaw/dist/compact-1mmJ_KWL.js
Objective: Extend the agent command session resolver to include delivery context parameters.
Before:
javascript const handleAgentCommand = (args) => { const sessionKey = resolveFromParams({ channel: args.channel, to: args.to // Missing: accountId, replyAccount }); return executeOnSession(sessionKey, args.message); };
After:
javascript const handleAgentCommand = (args) => { const sessionKey = resolveFromParams({ channel: args.channel, to: args.to, accountId: args.deliveryContext?.accountId, replyAccount: args.replyAccount }); return executeOnSession(sessionKey, args.message); };
Phase 4: Patch register.agent-DHoJWl4M.js β Fix Key Builder Usage
File: openclaw/dist/register.agent-DHoJWl4M.js
Objective: Replace incorrect resolveAgentMainSessionKey with buildAgentMainSessionKey(...).
Before (incorrect usage):
javascript const registerAgent = (context) => { const sessionKey = resolveAgentMainSessionKey( context.channel, context.accountId ); // resolveAgentMainSessionKey was being called with build semantics };
After (corrected):
javascript const registerAgent = (context) => { const sessionKey = buildAgentMainSessionKey( context.channel, context.accountId ); registerSession(sessionKey, context); };
Phase 5: Restart Gateway Service
bash sudo systemctl restart openclaw-gateway.service
π§ͺ Verification
Verification 1: Confirm Metadata Not Re-injected
Test: Send 3 consecutive messages in a Discord thread and inspect context.
bash
Message 1
openclaw agent –channel discord –to 1487654321 send “test message 1”
Message 2
openclaw agent –channel discord –to 1487654321 send “test message 2”
Message 3
openclaw agent –channel discord –to 1487654321 send “test message 3”
Expected: Context payload should show thread marker once, no repeated Thread starter or Chat history since last reply entries.
Check via gateway logs:
bash sudo journalctl -u openclaw-gateway.service -f | grep -E “(message_id|Thread starter|inject)”
Expected output: No instances of Thread starter appearing multiple times per session.
Verification 2: Confirm Correct Session Resolution
Test: CLI command should resolve to thread-specific session.
bash openclaw agent –channel discord –to 1487654321 send “verification check”
Expected gateway log output:
[INFO] Session resolution for: agent:discord:1487654321
[INFO] Delivery context matched: accountId=123456789
[INFO] Message queued for thread session
Not:
[INFO] Session resolution fallback: agent:*:main
[INFO] No delivery context match, using default
Verification 3: Verify New Session Behavior (Fresh Thread)
bash
Start entirely new Discord thread
openclaw agent –channel discord –to 999888777666 send “new thread test”
Expected: First message in new thread should still inject metadata (correct initial behavior preserved).
Check logs:
bash sudo journalctl -u openclaw-gateway.service | grep “new session” | tail -5
Expected: New session initializes with full metadata, subsequent turns in same thread do not.
Verification 4: Confirm Compound Fix in Registration
bash
Verify registration path uses correct key builder
openclaw status –verbose 2>&1 | grep -E “(session|accountId|key)”
Expected: Session keys formatted as agent:discord:123456789 (built, not resolved).
β οΈ Common Pitfalls
Pitfall 1: Patches Lost on Update/Reinstall
Problem: Modified files in openclaw/dist/ are compiled artifacts. Any npm update, pip install --upgrade, or manual reinstall will overwrite the patches.
Mitigation:
Create a post-install/patch restoration script:
bash #!/bin/bash
restore-discord-patches.sh
PATCH_DIR="./patches/discord-thread-fix" DIST_DIR="./openclaw/dist"
Apply patches in sequence
patch -p1 < “$PATCH_DIR/pi-embedded-D6PpOsxP.patch” patch -p1 < “$PATCH_DIR/gateway-cli-BjsM6fWb.patch” patch -p1 < “$PATCH_DIR/compact-1mmJ_KWL.patch” patch -p1 < “$PATCH_DIR/register.agent-DHoJWl4M.patch”
Restart service
sudo systemctl restart openclaw-gateway.service
Pitfall 2: Target Format Ambiguity
Problem: Discord targets may appear in multiple formats:
- Raw ID:
1487654321 - Prefixed:
channel:1487654321 - Mention format:
<#1487654321>
Mitigation: Ensure normalization handles all three. The patch includes handling for first two; mentions require additional parsing:
javascript function parseDiscordMention(target) { const match = target.match(/<#(\d+)>/); return match ? match[1] : target; }
Pitfall 3: Session Persistence Across Service Restarts
Problem: Testing changes requires clean state, but sessions persist in memory/db.
Mitigation:
bash
Option A: Clear session store
openclaw-cli session –clear –channel discord
Option B: Force new session for testing
openclaw agent –channel discord –to 1487654321 –new-session send “test”
Option C: Restart and verify fresh state
sudo systemctl restart openclaw-gateway.service sleep 2 openclaw status –channel discord
Pitfall 4: Mixed Version Environments
Problem: If running multiple OpenClaw instances or containers, the patch may be applied to wrong instance.
Mitigation:
bash
Verify which dist files are being used
ls -la $(openclaw which)/../dist/pi-embedded*.js md5sum $(openclaw which)/../dist/pi-embedded*.js
Confirm patch is applied
grep -c “Discord threads” $(openclaw which)/../dist/pi-embedded-D6PpOsxP.js
Pitfall 5: Regression from First Patch
Problem: The initial fix for Issue 1 introduced the resolveAgentMainSessionKey vs buildAgentMainSessionKey regression.
Mitigation: When applying patches, always check the compound effect. Review register.agent-DHoJWl4M.js after patching pi-embedded-D6PpOsxP.js to ensure both are compatible.
π Related Errors
ERR_SESSION_NOT_FOUND
CLI agent command resolves to non-existent session. Occurs when session key construction uses incorrect template (e.g., `agent:*:main` instead of `agent:discord:148...`).ERR_CONTEXT_EXCEEDS_LIMIT
Progressive metadata bloat causes context window to exceed model limits. Directly caused by volatile field re-injection in long threads.ERR_DUPLICATE_METADATA_INJECTION
Same metadata fields appearing multiple times in a single context payload. Diagnostic indicator for this bug.ERR_INVALID_TARGET_FORMAT
Discord target string fails normalization. Related to target format ambiguity pitfall.ERR_KEY_BUILD_MISMATCH
Registration path calls resolver with builder semantics, or vice versa. The compound regression introduced by the first patch.
Historical Context:
- v2026.3.9: Introduced thread-based Discord sessions but without proper metadata lifecycle management
- v2026.3.10: Partial fix addressed some session issues but introduced
resolveAgentMainSessionKeymisuse - v2026.3.11 (current): Full patch appliedβmetadata re-injection blocked for Discord threads, CLI resolver enhanced with delivery context lookup, key builder usage corrected