ECO-4.5 — Native Messaging Backend Abstraction¶
CONCEPT:ECO-4.0 | Pillar 4: Ecosystem & Peripherals
Provides a pluggable, transport-agnostic messaging framework enabling agents to send and receive messages across 17+ platforms with full KG integration.
Overview¶
The Native Messaging Backend Abstraction extends the agent-utilities ecosystem
with bidirectional, event-driven messaging across 17 platforms. Unlike MCP-based
request-response integrations, this system uses persistent connections with
AsyncIterator-based inbound event streaming for real-time messaging.
Design Philosophy¶
The architecture follows three proven patterns already in agent-utilities:
TraceBackendABC (harness/trace_backend.py) — abstract methods define the contract, concrete methods provide defaults, factory auto-detects backendsPluginRegistry(core/registry/plugin_adapter.py) — dynamic discovery viaimportlib.metadata.entry_pointsfor zero-config backend registrationstore_memory()/recall_memory()(knowledge_graph/core/engine_memory.py) — inbound messages auto-ingest into the KG as tiered episodic memory nodes
Architecture¶
graph TB
subgraph "agent_utilities/messaging/"
BASE["base.py<br/>MessagingBackend ABC"]
MODELS["models.py<br/>Pydantic Models"]
REG["registry.py<br/>Entry-point Discovery"]
ROUTER["router.py<br/>Inbound Event Router"]
CAP["capabilities.py<br/>Capability Matrix"]
KGI["kg_ingest.py<br/>KG Auto-Ingest"]
end
subgraph "backends/ (17 platforms)"
D[discord.py] --> BASE
S[slack.py] --> BASE
T[telegram.py] --> BASE
W[whatsapp.py] --> BASE
MS[teams.py] --> BASE
GC[googlechat.py] --> BASE
GM[googlemeet.py] --> BASE
MM[mattermost.py] --> BASE
MX[matrix.py] --> BASE
IR[irc.py] --> BASE
SG[signal.py] --> BASE
IM[imessage.py] --> BASE
LN[line.py] --> BASE
TW[twitch.py] --> BASE
SY[synology.py] --> BASE
VC[voicecall.py] --> BASE
NC[nextcloud.py] --> BASE
end
ROUTER -->|"route to"| PLANNER["Planner Graph Agent<br/>(CONCEPT:ORCH-1.1)"]
KGI -->|"store_memory()"| KG["Knowledge Graph<br/>(CONCEPT:KG-2.1)"]
PLANNER -->|"recall_memory()"| KG
Inbound Message Flow¶
sequenceDiagram
participant P as Platform (Discord/Slack/...)
participant B as MessagingBackend
participant R as InboundRouter
participant KG as Knowledge Graph
participant PL as Planner Graph Agent
participant S as Specialist Agents
P->>B: New message event
B->>R: yield InboundEvent
R->>KG: store_memory(episodic)
R->>KG: recall_memory(context)
KG-->>R: Related memories
R->>PL: Route with KG context
PL->>S: Orchestrate specialists
S-->>PL: Response
PL->>B: send_message(response)
B->>P: Deliver response
Installation¶
# Single backend
pip install agent-utilities[messaging-discord]
# Multiple backends
pip install agent-utilities[messaging-discord,messaging-slack,messaging-telegram]
# All 17 backends
pip install agent-utilities[messaging]
Quick Start¶
from agent_utilities.messaging import MessagingRegistry, MessagingBackend
# Discover installed backends
registry = MessagingRegistry()
print(registry.list_backends()) # ['discord', 'slack', ...]
# Create and connect a backend
discord = registry.create_backend("discord")
await discord.connect()
# Send a message
result = await discord.send_message("#general", "Hello from agent!")
# Listen for inbound messages
async for event in discord.listen():
print(f"[{event.platform}] {event.user_name}: {event.content}")
Configuration (XDG config.json)¶
All messaging configuration is managed through the unified XDG config file:
See: ECO-4.5 Messaging Configuration Guide for the complete per-platform reference with all keys and env var mappings.
Config Priority Chain¶
1. Environment variable (MESSAGING_DISCORD_TOKEN=...) ← highest
2. XDG config.json (~/.config/agent-utilities/config.json)
3. .env file (project-local)
4. Platform-native env vars (DISCORD_BOT_TOKEN) ← lowest
Minimal config.json Example¶
{
"messaging_enabled_backends": ["discord", "slack"],
"messaging_kg_ingest": true,
"messaging_route_to_planner": true,
"messaging_discord_token": "BOT_TOKEN_HERE",
"messaging_slack_token": "xoxb-...",
"messaging_slack_app_token": "xapp-..."
}
How It Works¶
flowchart LR
CFG["config.json"] -->|"_load_xdg_json_config()"| ENV["Environment Variables"]
ENV -->|"AgentConfig (Pydantic)"| FIELDS["config.messaging_*"]
ENV -->|"MessagingRegistry._auto_config()"| BACKEND["Backend Instance"]
FIELDS -->|"config.reload()"| HOT["Hot-reload at runtime"]
All messaging_* keys in config.json are:
1. Loaded at startup by _load_xdg_json_config() (uppercased to env vars)
2. Parsed into first-class AgentConfig fields (accessible as config.messaging_discord_token)
3. Read by MessagingRegistry._auto_config() when creating backend instances
XDG Directory Layout¶
~/.config/agent-utilities/
├── config.json ← All messaging config lives here
├── mcp_config.json
└── a2a_config.json
~/.local/share/agent-utilities/
├── kg/knowledge_graph.db ← Messages stored here as memory nodes
├── messaging/
│ ├── sessions/ ← Backend-specific auth state
│ └── history/ ← Local message history cache
└── ...
WhatsApp Dual Mode¶
{
"messaging_whatsapp_use_business_api": true,
"messaging_whatsapp_token": "<access-token>",
"messaging_whatsapp_phone_number_id": "<phone-id>"
}
Set messaging_whatsapp_use_business_api to false (default) for the
neonize bridge, which connects via QR code with no token required.
Capability Matrix¶
| Capability | Discord | Slack | Telegram | Teams | GChat | GMeet | MM | Matrix | IRC | Signal | iMsg | LINE | Twitch | Syno | Voice | NC | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Send text | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Media | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ |
| Threads | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
| Reactions | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ |
| Typing | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Inbound | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Voice | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
Module Reference¶
| Module | Purpose | CONCEPT |
|---|---|---|
messaging/__init__.py |
Public API surface | ECO-4.5 |
messaging/base.py |
MessagingBackend ABC |
ECO-4.5 |
messaging/models.py |
Pydantic data models | ECO-4.5 |
messaging/registry.py |
Entry-point backend discovery | ECO-4.5 |
messaging/capabilities.py |
Platform capability matrix | ECO-4.5 |
messaging/router.py |
Inbound → Planner Graph Agent | ECO-4.5 + ORCH-1.1 |
messaging/kg_ingest.py |
KG auto-ingest | ECO-4.5 + KG-2.1 |
messaging/backends/*.py |
17 platform implementations | ECO-4.5 |
KG Integration (CONCEPT:KG-2.1)¶
Inbound messages are automatically ingested as episodic memory nodes:
engine.store_memory(
content="[DISCORD] Message from user in #general: Hello!",
memory_type="episodic",
tags=["platform:discord", "channel:general", "user:alice"],
trust_score=0.7,
)
Agent responses are stored as semantic memory (longer half-life):
engine.store_memory(
content="[DISCORD] Agent response in #general: I can help with that.",
memory_type="semantic",
trust_score=0.9,
)
Both leverage the existing MemoryDecayConfig (CONCEPT:KG-2.3) for
Ebbinghaus-curve-based relevance decay over time.
Cross-References¶
- CONCEPT:ORCH-1.1 — Planner Graph Agent receives routed messages
- CONCEPT:KG-2.1 — Tiered Memory for conversation persistence
- CONCEPT:KG-2.3 — Memory decay for message relevance scoring
- CONCEPT:ECO-4.0 — Plugin registry pattern for backend discovery
- CONCEPT:OS-5.0 — XDG paths for session/config storage