Channel Message Metadata Injection - Configuration Guide
Guide to configuring OpenClaw's channel message metadata injection for trusted vs untrusted contexts, including environment variables and pairing policy options.
🔍 Symptoms
When messages arrive from integrated channels (Telegram, Discord), OpenClaw injects JSON metadata blocks at the message prefix:
Example - Telegram Message with Metadata:
[Channel: Telegram | ChatID: -1001234567890 | SenderID: 987654321 | Trusted: false | Timestamp: 1709529600]
{"channel":"telegram","chat_id":-1001234567890,"sender_id":987654321,"trusted":false,"ts":1709529600}
Your message content starts here...Example - Discord Message with Metadata:
[Channel: Discord | GuildID: 123456789 | ChannelID: 987654321 | UserID: 555555555 | Trusted: false]
{"channel":"discord","guild_id":"123456789","channel_id":"987654321","user_id":"555555555","trusted":false,"ts":1709529600}
Bot message content here...User-Reported Issues:
- Visual noise in conversation context for personal assistant bots
- Agent must mentally filter out metadata prefix in every message
- Increased token consumption in long-running conversations
- Cluttered context history after dozens of exchanges
Current Workaround Limitations:
// In system prompt - unreliable and token-expensive
Remember: Ignore all [Channel: ...] and JSON metadata blocks. They are internal markers only.🧠 Root Cause
OpenClaw’s metadata injection serves a critical security architecture purpose:
Security Design Rationale:
- Provenance Tracking: Every message carries sender identity to prevent spoofing attacks
- Trust Verification: The
trustedflag enables authorization decisions at runtime - Audit Trail: Timestamps and IDs support forensic analysis of conversation history
- Channel Isolation: Prevents cross-channel message injection attacks
Architectural Flow:
Channel Adapter → Metadata Injection → Context Enrichment → Agent Processing
↓
[Channel: X | SenderID: Y | Trusted: Z]
↓
JSON block appended to message contentWhy Disabling is Problematic: The metadata serves dual purposes:
- Runtime trust decisions (used by pairing policies)
- Context enrichment (injected into conversation history)
These are currently coupled—disabling injection removes both capabilities.
Configuration Gap: No current option exists to:
- Enable trust verification without context pollution
- Mark specific channels/senders as trusted by default
- Control metadata verbosity level
🛠️ Step-by-Step Fix
Implemented Solution (OpenClaw 2026.3.8+)
The feature adds three configuration options:
Option 1: Global Metadata Injection Toggle
Set the environment variable or configuration file:
# Environment variable
CHANNEL_METADATA_INJECTION=false
# Or in config.yaml
channels:
metadata:
injection: falseBefore:
[Channel: Telegram | ChatID: -1001234567890 | SenderID: 987654321 | Trusted: false]
{"channel":"telegram","chat_id":-1001234567890,"sender_id":987654321,"trusted":false,"ts":1709529600}
Hello, can you help me with my schedule?After:
Hello, can you help me with my schedule?Option 2: Per-Channel Trust Configuration
# config.yaml
channels:
telegram:
trusted:
- sender_id: 987654321 # Known owner
- sender_id: 111222333 # Trusted family member
metadata:
injection: true
show_trusted: false # Hide metadata for trusted senders
discord:
trusted:
- user_id: 555555555
metadata:
injection: falseOption 3: Pairing Policy Integration
# config.yaml
pairing:
policies:
- name: trusted-owner
type: sender-whitelist
channels: [telegram, discord]
sender_ids:
- 987654321
- 555555555
metadata_level: minimal # Only essential fields
context_exclude_metadata: trueConfiguration Matrix
| Scenario | injection | show_trusted | metadata_level |
|---|---|---|---|
| Maximum Security | true | true | full |
| Trusted DM Only | true | false | essential |
| No Metadata | false | N/A | N/A |
| Minimal Context | true | true | minimal |
🧪 Verification
Verify Configuration is Active
Check Environment Variable:
# Linux/macOS
echo $CHANNEL_METADATA_INJECTION
# Output: false
# Windows (PowerShell)
$env:CHANNEL_METADATA_INJECTION
# Output: falseCheck Running Configuration:
# Using OpenClaw CLI
openclaw config show --filter metadata
# Expected output:
# {
# "channels": {
# "metadata": {
# "injection": false,
# "levels": {...}
# }
# }
# }Verify Message Processing
Test Telegram message with metadata disabled:
# Send test message from trusted sender
curl -X POST https://api.telegram.org/bot{BOT_TOKEN}/sendMessage \
-d "chat_id=987654321" \
-d "text=Test message for verification"
# Check OpenClaw logs
tail -f /var/log/openclaw/messages.log | grep -A2 "Test message"Expected log output (metadata disabled):
[2026-03-15 10:30:45] INFO channel.telegram - Message received from sender:987654321
[2026-03-15 10:30:45] DEBUG channel.telegram - Trust check: PASSED (whitelisted)
[2026-03-15 10:30:45] DEBUG channel.telegram - Metadata injection: DISABLED
[2026-03-15 10:30:45] DEBUG context - Message queued: "Test message for verification"Test untrusted sender (metadata should still appear):
# When message from unknown sender arrives
[2026-03-15 10:31:00] WARN channel.telegram - Unknown sender: 999888777
[2026-03-15 10:31:00] DEBUG channel.telegram - Metadata injection: ENABLED (untrusted)
[2026-03-15 10:31:00] DEBUG context - Message queued with metadataVerify Token Reduction
# Compare conversation history token count
openclaw context stats --history
# Before (metadata injection: true)
# Total tokens in last 50 messages: 12,450
# After (metadata injection: false)
# Total tokens in last 50 messages: 9,230
# Reduction: ~26%⚠️ Common Pitfalls
⚠️ Common Pitfalls
1. Partial Configuration (Most Common)
Setting only injection: false without per-sender trust configuration:
# WRONG - Disables metadata for ALL messages including security-critical ones
channels:
metadata:
injection: false
# CORRECT - Maintains security boundary
channels:
metadata:
injection: true
telegram:
trusted:
- sender_id: 987654321
# Untrusted senders still receive metadata
# Trusted senders get clean context2. Conflicting Configuration Files
The following precedence order is used (last wins):
- Default values (built into binary)
config.yamlin project root~/.openclaw/config.yaml(user-level)- Environment variables
Debug conflicting settings:
openclaw config debug --show-merged3. Telegram vs Discord ID Formats
Telegram uses numeric IDs; Discord uses snowflake IDs (18-digit strings):
# CORRECT for Telegram
channels:
telegram:
trusted:
- sender_id: 987654321 # Numeric
# CORRECT for Discord
channels:
discord:
trusted:
- user_id: "555555555555555555" # String with quotes4. Pairing Policy Override
If pairing.policies specifies metadata_level: full, it overrides channel-level settings:
# Channel config says no metadata
channels:
telegram:
metadata:
injection: false
# But pairing policy says full metadata
pairing:
policies:
- name: security-policy
metadata_level: full # THIS OVERRIDES channel config
# Result: Metadata WILL be injected5. Hot-Reload Not Applied
Changes to config.yaml require restart unless hot-reload is enabled:
# Enable hot-reload
openclaw server --config-watch
# Or set environment variable
OPENCLAW_CONFIG_WATCH=true🔗 Related Errors
Related Configuration Issues
| Issue | Description | Reference |
|---|---|---|
| TRUST-001 | Untrusted sender bypasses pairing policy | Sender whitelist not enforced |
| CONTEXT-042 | Metadata persists in conversation history | context_exclude_metadata not set |
| CONFIG-117 | Environment variable ignored on Windows | Use setx instead of export |
Related Historical Issues
| Issue | Description | Status |
|---|---|---|
| #847 | Metadata injection causes token overflow in long conversations | Fixed in v2026.2.1 |
| #912 | JSON metadata block not valid JSON (missing outer braces) | Fixed in v2026.3.0 |
| #1043 | Discord channel ID not included in metadata | Fixed in v2026.3.5 |