Page:
Data Flow 04 Message Classification
Pages
Architecture Commands and API
Architecture Context System
Architecture Core Engine
Architecture Event Sourcing
Architecture Generative Reflection
Architecture Helpers
Architecture Journal System
Architecture LLM Interaction
Architecture LLM Providers
Architecture Logging
Architecture Memory and Sleep
Architecture Overview
Architecture Persona Protection
Architecture Prompt System
Architecture RAG Implementation
Architecture Resilience System
Architecture Safety System
Architecture Self Management
Architecture Sub Agent Delegation
Architecture Task Assessment
Architecture Token Management
Architecture Tool System
Configuration Reference
Context and Memory Flow Analysis
Data Flow 01 Context Compaction
Data Flow 02 ReAct Loop
Data Flow 03 Memory Consolidation
Data Flow 04 Message Classification
Data Flow 05 Entity Profile System
Data Flow 06 Tool Execution
Data Flow 07 Sleep Mode Transitions
Data Flow 08 LLM Provider Interaction
Data Flow 09 Self Management Operations
Home
LLM Decision Patterns
Research Foundations
User Guide 00 Index
User Guide 01 Getting Started
User Guide 02 Configuration and Customization
User Guide 03 Advanced Capabilities
User Guide 04 Troubleshooting
No results
2
Data Flow 04 Message Classification
blightbow edited this page 2025-12-09 02:36:45 +00:00
Table of Contents
- Data Flow 04: Message Classification
- Overview
- Related Documents
- 1. Message Entry Point
- 2. Classification Flow
- 3. Classification Rules
- Rule 0: Disabled State Check
- Rule 1: Self-Message Handling
- Rule 2: Direct Addressing (@mention)
- Rule 3: Direct Messages
- Rule 4: Assistant Cross-Talk
- Rule 5: Permission-Based Trigger
- Rule 6: Channel Configuration
- Rule 7: Room Message Default
- Rule 8: Default Fallback
- 4. Classification Results
- 5. Trust Scoring
- 6. Security Notes
- 7. Key Files
Data Flow 04: Message Classification
Engineering documentation series - Data flows in the AI Assistant system
Overview
The message classification system routes incoming messages to appropriate handlers based on source type, sender permissions, and addressing. Classification determines whether a message triggers AI action, provides context, or is ignored.
Related Documents
| Document | Description |
|---|---|
| Data-Flow-02-ReAct-Loop | How triggers lead to execution |
1. Message Entry Point
Hook Chain
Evennia Message System
└─> AssistantCharacter.at_msg_receive()
└─> classify_message()
└─> Handler based on classification
2. Classification Flow
┌─────────────────────────────────────────────────────────────────────────────┐
│ MESSAGE RECEIVED │
│ assistant_character.py::at_msg_receive() │
│ Input: text, from_obj, **kwargs │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ EXTRACT OOB DATA │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Message formats: │
│ - str: Plain text │
│ - tuple: (text_str, oob_dict) - Evennia's standard format │
│ │
│ Merge OOB sources (kwargs take precedence): │
│ merged_oob = {**oob_data, **kwargs} │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ DETECT SOURCE TYPE │
│ messaging/classification.py::detect_source_type() │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Priority order: │
│ 1. from_channel presence → "channel" │
│ 2. type key in OOB tuple → "say"/"pose"/"whisper" │
│ 3. type key in kwargs → fallback │
│ 4. Pattern matching → "page" (HEURISTIC ONLY) │
│ │
│ Returns: "channel" | "say" | "pose" | "whisper" | "page" | "emit" | "unknown│
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ CLASSIFICATION RULES (ORDER MATTERS) │
│ messaging/classification.py::classify_message() │
└─────────────────────────────────────────────────────────────────────────────┘
3. Classification Rules
Rules are evaluated in order. First match wins.
Rule 0: Disabled State Check
┌─────────────────────────────────────────────────────────────────────────────┐
│ RULE 0: INTERACTION DISABLED │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Condition: interaction_enabled == False │
│ Result: IGNORE │
│ Reason: "interaction_disabled" │
│ │
│ This overrides ALL other rules including permissions and addressing. │
└─────────────────────────────────────────────────────────────────────────────┘
Rule 1: Self-Message Handling
┌─────────────────────────────────────────────────────────────────────────────┐
│ RULE 1: SELF-MESSAGE DETECTION │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Condition: sender == self │
│ │
│ Sub-rules: │
│ │
│ 1a. If assistant_message flag set: │
│ → IGNORE (prevent conversation loops) │
│ Reason: "self_message_conversational" │
│ │
│ 1b. If command_output_buffer active: │
│ → CAPTURE (return True, not tuple) │
│ Action: Append to ndb.command_output_buffer │
│ Used by: CommandExecutionTool │
│ │
│ 1c. Otherwise (uncaptured command output): │
│ → CONTEXT │
│ Reason: "self_command_output_uncaptured" │
└─────────────────────────────────────────────────────────────────────────────┘
Rule 2: Direct Addressing (@mention)
┌─────────────────────────────────────────────────────────────────────────────┐
│ RULE 2: DIRECT ADDRESSING │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Condition: enable_addressing == True │
│ AND @mention matches assistant_key │
│ │
│ Detection: messaging/classification.py::detect_addressing() │
│ 1. OOB metadata "addressing" key (trustworthy) │
│ 2. @mention pattern in text (user-generated) │
│ │
│ Result: TRIGGER │
│ Reason: "direct_addressing" │
│ Metadata: {addressing, sender, source_type} │
└─────────────────────────────────────────────────────────────────────────────┘
Rule 3: Direct Messages
┌─────────────────────────────────────────────────────────────────────────────┐
│ RULE 3: DIRECT/PRIVATE MESSAGES │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Condition: source_type in ["whisper", "page"] │
│ │
│ Result: TRIGGER │
│ Reason: "direct_message" │
│ Metadata: {source_type, sender} │
└─────────────────────────────────────────────────────────────────────────────┘
Rule 4: Assistant Cross-Talk
┌─────────────────────────────────────────────────────────────────────────────┐
│ RULE 4: OTHER ASSISTANT MESSAGES │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Condition: assistant_message flag set (from another assistant) │
│ │
│ Result: CONTEXT │
│ Reason: "assistant_crosstalk" │
│ Metadata: {assistant_key, sender, source_type} │
│ │
│ Purpose: Prevent assistant-to-assistant response loops │
└─────────────────────────────────────────────────────────────────────────────┘
Rule 5: Permission-Based Trigger
┌─────────────────────────────────────────────────────────────────────────────┐
│ RULE 5: SENDER HAS TRIGGER PERMISSION │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Check: messaging/trust.py::sender_has_trigger_permission() │
│ │
│ Permission sources: │
│ - Global permissions (db.trigger_permissions["global"]) │
│ - Channel-specific permissions (db.trigger_permissions["channels"]) │
│ │
│ Default global: ["Developer", "Admin"] │
│ │
│ Result: TRIGGER │
│ Reason: "permitted_sender" │
│ Metadata: {permission_level, sender, source_type} │
└─────────────────────────────────────────────────────────────────────────────┘
Rule 6: Channel Configuration
┌─────────────────────────────────────────────────────────────────────────────┐
│ RULE 6: CHANNEL-SPECIFIC CONFIGURATION │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Condition: source_type == "channel" AND channel in channel_configs │
│ │
│ Config options per channel: │
│ - default_action: "TRIGGER" | "CONTEXT" | "IGNORE" │
│ - keywords: List of trigger keywords │
│ │
│ Result: Based on channel config │
│ Reason: "channel_default" │
└─────────────────────────────────────────────────────────────────────────────┘
Rule 7: Room Message Default
┌─────────────────────────────────────────────────────────────────────────────┐
│ RULE 7: ROOM MESSAGES │
│ ─────────────────────────────────────────────────────────────────────────── │
│ Condition: source_type in ["say", "pose"] │
│ │
│ Result: CONTEXT │
│ Reason: "room_message_default" │
│ │
│ Purpose: Be aware of room activity without auto-responding │
└─────────────────────────────────────────────────────────────────────────────┘
Rule 8: Default Fallback
┌─────────────────────────────────────────────────────────────────────────────┐
│ RULE 8: DEFAULT │
│ ─────────────────────────────────────────────────────────────────────────── │
│ No other rules matched │
│ │
│ Result: IGNORE │
│ Reason: "unclassified_unknown" │
└─────────────────────────────────────────────────────────────────────────────┘
4. Classification Results
| Classification | Meaning | Action |
|---|---|---|
TRIGGER |
Message requires AI response | Queue to assistant script via handle_trigger_message() |
CONTEXT |
Informational, store for context | Add to context buffer via handle_context_message() |
CAPTURE |
Command output being captured | Append to tool buffer (returns True, not tuple) |
IGNORE |
Discard message | No action |
5. Trust Scoring
TRIGGER and CONTEXT messages include a source_trust score for memory reliability (O-Mem style).
Trust Calculation
messaging/trust.py::calculate_source_trust()
Factors:
- Source type base score (SOURCE_TRUST_SCORES dict)
- Sender trust modifier (history-based)
- Trust override flag (for verified sources)
Source Trust Scores
| Source Type | Base Score | Rationale |
|---|---|---|
whisper |
0.95 | Direct, private communication |
page |
0.90 | Cross-room private message |
say |
0.80 | In-room speech, witnessed |
pose |
0.75 | In-room action, interpreted |
channel |
0.70 | Public broadcast |
emit |
0.50 | Anonymous message |
unknown |
0.30 | Unverified source |
6. Security Notes
┌─────────────────────────────────────────────────────────────────────────────┐
│ SECURITY-CRITICAL │
│ ─────────────────────────────────────────────────────────────────────────── │
│ │
│ OOB Metadata Precedence (trustworthiness): │
│ 1. **kwargs (highest) - Server-generated via message path │
│ 2. tuple OOB data - Embedded by Evennia's message system │
│ 3. Pattern matching (HEURISTIC ONLY) - Fallback for legacy │
│ │
│ WARNING: Pattern matching is NOT secure for: │
│ - Authentication decisions │
│ - Authorization decisions │
│ - Security-critical routing │
│ │
│ User-controlled message content is UNSAFE and susceptible to injection. │
│ Always use server-side permission checks for security operations. │
└─────────────────────────────────────────────────────────────────────────────┘
7. Key Files
| File | Key Functions | Purpose |
|---|---|---|
messaging/classification.py |
classify_message() |
Main classification logic |
messaging/classification.py |
detect_source_type() |
Source type detection |
messaging/classification.py |
detect_addressing() |
@mention detection |
messaging/classification.py |
handle_trigger_message() |
Queue TRIGGER to script |
messaging/classification.py |
handle_context_message() |
Buffer CONTEXT messages |
messaging/trust.py |
calculate_source_trust() |
Trust score calculation |
messaging/trust.py |
sender_has_trigger_permission() |
Permission checking |
messaging/trust.py |
get_sender_trust_modifier() |
History-based modifier |
messaging/batching.py |
process_message_batch() |
Batch processing |
messaging/batching.py |
filter_and_sanitize_batch() |
Content sanitization |
assistant_character.py |
at_msg_receive() |
Entry point hook |
Document created: 2025-12-06 Updated: 2025-12-09 - Migrated references to messaging/ package