Interface Path System
The Interface Path system is a unified hierarchical addressing mechanism used throughout Synthetic Heart to consistently identify and route messages across different chat platforms and conversation contexts.
Overview
Interface paths provide a standardized way to address conversations regardless of the underlying platform (Telegram, Discord, Matrix, etc.). This abstraction layer enables:
Consistent Conversation Identification: Same addressing format across all interfaces
Thread Support: Hierarchical paths support nested conversations (threads, topics)
Platform Agnostic Routing: Components can work with any interface without platform-specific code
Backward Compatibility: Legacy chat_id/thread_id systems are supported through conversion utilities
Path Format
Interface paths follow a hierarchical structure separated by forward slashes:
interface_name/target_identifier[/thread_identifier]
Components:
interface_name: The interface type (e.g.,telegram_bot,discord_bot,matrix)target_identifier: Primary conversation identifier (chat_id, channel_id, room_id, etc.)thread_identifier(optional): Thread or sub-conversation identifier
Examples:
telegram_bot/-1001234567890- Telegram channel/group chattelegram_bot/123456789/987- Telegram chat with threaddiscord_bot/987654321/123456- Discord channel with threadmatrix/!room:matrix.org/$event- Matrix room with thread event
Core Utilities
The core/interface_path_utils.py module provides essential functions for working with interface paths:
Building Paths
from core.interface_path_utils import build_interface_path
# Build from components
path = build_interface_path('telegram_bot', '123456789', '987')
# Result: 'telegram_bot/123456789/987'
# Build without thread
path = build_interface_path('telegram_bot', '123456789')
# Result: 'telegram_bot/123456789'
Legacy Conversion
from core.interface_path_utils import build_interface_path_from_legacy
# Convert old chat_id/thread_id format
path = build_interface_path_from_legacy('telegram_bot', '123456789', '987')
# Result: 'telegram_bot/123456789/987'
Parsing Paths
from core.interface_path_utils import parse_interface_path
# Parse path into components
components = parse_interface_path('telegram_bot/123456789/987')
# Result: {'interface': 'telegram_bot', 'target': '123456789', 'thread': '987'}
# Parse without thread
components = parse_interface_path('telegram_bot/123456789')
# Result: {'interface': 'telegram_bot', 'target': '123456789', 'thread': None}
Validation
from core.interface_path_utils import is_valid_interface_path
# Validate path format
valid = is_valid_interface_path('telegram_bot/123456789/987') # True
valid = is_valid_interface_path('invalid_path') # False
Database Integration
The chat history cache has been updated to use interface paths as the primary key:
Schema Changes:
Removed separate
chat_id,interface,thread_idcolumnsAdded single
interface_path VARCHAR(512)columnUpdated all indexes and constraints
Migration Impact:
All chat history operations now use interface paths:
save_chat_message(interface_path, ...)load_chat_history(interface_path, ...)clear_chat_history(interface_path, ...)
Message Flow Integration
Interface paths are integrated throughout the message processing pipeline:
Interface Reception: Each interface generates an interface path when receiving messages
Context Building: Paths are included in message context dictionaries
LLM Processing: Prompts include interface path information for context-aware responses
Action Routing: Message plugins reconstruct paths for proper delivery
Response Sending: Interfaces parse paths to extract platform-specific identifiers
Example Flow (Telegram):
# 1. Interface generates path
interface_path = build_interface_path('telegram_bot', str(chat_id), str(thread_id))
# 2. Context includes path
context = {
'interface_path': interface_path,
'message': user_message,
# ... other context
}
# 3. LLM receives path in prompt
prompt = f"Respond to message from {interface_path}: {user_message}"
# 4. Action includes path
action = {
'action': 'message_telegram_bot',
'text': response,
'interface_path': interface_path # Critical for routing
}
# 5. Plugin reconstructs and sends
send_payload = {
'text': response,
'interface_path': interface_path
}
Interface-Specific Implementations
Telegram Bot
Path Format:
telegram_bot/chat_id[/thread_id]Generation:
build_interface_path('telegram_bot', str(message.chat_id), str(thread_id))Validation: Requires
interface_pathin message actionsThread Support: Handles Telegram topic threads
Matrix Interface
Path Format:
matrix/room_identifier[/thread_event_id]Generation:
build_interface_path('matrix', room_identifier, thread_event_id)Thread Support: Uses Matrix thread events
Ollama Server
Path Format:
ollama_serve/conversation_idGeneration:
build_interface_path('ollama_serve', chat_id)Thread Support: Single-level conversations
Best Practices
Always Use Interface Paths:
Never pass separate
chat_idandthread_idparametersInclude
interface_pathin all message-related actionsUse
input.payload.source.interface_pathfor replies
Validation:
Validate paths before using:
is_valid_interface_path(path)Handle invalid paths gracefully with fallback mechanisms
Logging:
Include interface paths in debug logs for traceability
Use paths instead of legacy identifiers in error messages
Error Message Routing
Changed in version 1.0: LLM error messages now correctly follow the interface_path from the original message.
When LLM processing fails (JSON parsing errors, timeouts, validation failures), the system sends fallback error messages. These messages are automatically routed to the same interface and conversation using the preserved interface_path.
Implementation:
The error routing is handled in core/message_chain.py → send_llm_fallback_message():
# Extract interface_path from message or context
interface_path = getattr(message, 'interface_path', None)
if not interface_path and context:
interface_path = context.get('interface_path')
# Route through transport layer with preserved path
await universal_send(
bot.send_message,
chat_id,
text=fallback_text,
interface_path=interface_path, # Ensures correct routing
is_llm_response=True
)
Benefits:
Consistent Error Delivery: Errors appear in the same chat where the problem occurred
Context Preservation: Users see errors in the correct conversation thread
Interface Agnostic: Works across Telegram, Discord, Matrix, etc.
Migration:
Use
build_interface_path_from_legacy()for gradual migrationUpdate components incrementally to avoid breaking changes
Troubleshooting
Common Issues:
Missing interface_path in actions: Ensure LLM prompts include path extraction instructions
Path reconstruction failures: Verify message_plugin payload building includes path
Thread context loss: Check that thread identifiers are properly preserved
Interface routing errors: Validate path parsing in interface handlers
Debug Commands:
# Check interface path parsing
python3 -c "from core.interface_path_utils import parse_interface_path; print(parse_interface_path('telegram_bot/123/456'))"
# Validate path format
python3 -c "from core.interface_path_utils import is_valid_interface_path; print(is_valid_interface_path('telegram_bot/123/456'))"