{
  "feature": "openclaw-messaging-channel",
  "version": "1.0.0",
  "description": "Platform-agnostic messaging channel integration supporting Discord, Telegram, Slack, and 85+ platforms with unified message routing and delivery",
  "category": "integration",
  "tags": [
    "messaging",
    "channels",
    "discord",
    "telegram",
    "multi-platform"
  ],
  "actors": [
    {
      "id": "user",
      "name": "End User",
      "type": "human"
    },
    {
      "id": "platform",
      "name": "Messaging Platform",
      "type": "external"
    },
    {
      "id": "channel_plugin",
      "name": "Channel Plugin",
      "type": "system"
    },
    {
      "id": "gateway",
      "name": "OpenClaw Gateway",
      "type": "system"
    }
  ],
  "fields": [
    {
      "name": "channel_id",
      "type": "text",
      "required": true,
      "label": "Channel ID"
    },
    {
      "name": "account_id",
      "type": "text",
      "required": true,
      "label": "Account ID"
    },
    {
      "name": "message_id",
      "type": "text",
      "required": true,
      "label": "Message ID"
    },
    {
      "name": "platform_user_id",
      "type": "text",
      "required": true,
      "label": "Platform User ID"
    },
    {
      "name": "platform_chat_id",
      "type": "text",
      "required": false,
      "label": "Chat/Channel ID"
    },
    {
      "name": "thread_id",
      "type": "text",
      "required": false,
      "label": "Thread ID"
    },
    {
      "name": "message_text",
      "type": "text",
      "required": true,
      "label": "Message Content"
    },
    {
      "name": "attachments",
      "type": "json",
      "required": false,
      "label": "Attachments"
    },
    {
      "name": "message_type",
      "type": "select",
      "required": true,
      "label": "Message Type",
      "options": [
        {
          "value": "text",
          "label": "Text"
        },
        {
          "value": "image",
          "label": "Image"
        },
        {
          "value": "file",
          "label": "File"
        },
        {
          "value": "audio",
          "label": "Audio"
        },
        {
          "value": "video",
          "label": "Video"
        },
        {
          "value": "command",
          "label": "Command"
        },
        {
          "value": "button_click",
          "label": "Button Click"
        },
        {
          "value": "emoji_reaction",
          "label": "Emoji Reaction"
        }
      ]
    },
    {
      "name": "peer_kind",
      "type": "select",
      "required": true,
      "label": "Peer Type",
      "options": [
        {
          "value": "direct",
          "label": "Direct Message (1:1)"
        },
        {
          "value": "group",
          "label": "Group Chat"
        },
        {
          "value": "channel",
          "label": "Channel"
        },
        {
          "value": "thread",
          "label": "Thread"
        },
        {
          "value": "topic",
          "label": "Topic"
        }
      ]
    },
    {
      "name": "dm_policy",
      "type": "select",
      "required": false,
      "label": "DM Security Policy",
      "options": [
        {
          "value": "pairing",
          "label": "Device Pairing Required"
        },
        {
          "value": "allowlist",
          "label": "Allowlist Only"
        },
        {
          "value": "open",
          "label": "Open (allowFrom=*)"
        },
        {
          "value": "disabled",
          "label": "All DMs Blocked"
        }
      ]
    },
    {
      "name": "response_text",
      "type": "text",
      "required": false,
      "label": "Response Text"
    },
    {
      "name": "response_components",
      "type": "json",
      "required": false,
      "label": "Response Components"
    },
    {
      "name": "message_action",
      "type": "select",
      "required": false,
      "label": "Message Action",
      "options": [
        {
          "value": "send",
          "label": "Send"
        },
        {
          "value": "reply",
          "label": "Reply"
        },
        {
          "value": "edit",
          "label": "Edit"
        },
        {
          "value": "delete",
          "label": "Delete"
        },
        {
          "value": "reaction",
          "label": "Reaction"
        },
        {
          "value": "pin",
          "label": "Pin"
        },
        {
          "value": "kick",
          "label": "Kick (moderation)"
        },
        {
          "value": "ban",
          "label": "Ban (moderation)"
        },
        {
          "value": "timeout",
          "label": "Timeout (moderation)"
        }
      ]
    },
    {
      "name": "text_chunk_limit",
      "type": "number",
      "required": false,
      "label": "Text Chunk Limit"
    }
  ],
  "rules": {
    "inbound_message_handling": {
      "message_reception": "Inbound flow:\n1. Platform sends webhook/event to gateway\n2. Channel plugin parses platform format\n3. Normalize to unified structure\n4. Extract: message_id, sender, content, attachments, metadata\n5. Route via message-routing system\n6. Dispatch to target agent\n",
      "message_normalization": "Platform formats converted to unified:\n- Discord: Message object → message_text + attachments\n- Telegram: Update → message_text + media URLs\n- Slack: event_callback → message_text + blocks\n- Matrix: m.room.message → message_text + files\nPlatform differences abstracted from agent.\n",
      "user_identification": "Platform user IDs normalized:\n- Discord: Snowflake ID (int64)\n- Telegram: Integer ID\n- Slack: U-prefixed string\n- Matrix: @user:server.com\nStored with channel prefix for lookup.\n",
      "attachment_handling": "Supported types: image, file, audio, video.\nMax size: platform-dependent (8-25MB typical).\nStored as: attachments[{ type, url, name, size }].\nURL handling: some require auth, others public.\n"
    },
    "outbound_message_sending": {
      "send_flow": "Agent generates response:\n1. Message tool called with { text, components, actions }\n2. Message tool routes to channel plugin\n3. Plugin transforms to platform format\n4. Send via platform API\n5. Track delivery status (sent, failed, rate-limited)\n6. Update session.lastChannel/lastTo\n",
      "message_splitting": "For messages exceeding platform limits:\n- Discord: split at 2000 chars\n- Telegram: split at 4096 chars\n- Slack: split at 4000 chars\nEach chunk sent as separate message.\n",
      "component_rendering": "Components adapted per platform:\n- Discord: Rich embeds, buttons, select menus, modals\n- Telegram: Inline buttons (callback_data), keyboards\n- Slack: Block Kit (buttons, select menus)\n- WhatsApp: Template buttons (max 3)\nPlatform limitations: too many buttons → error or truncation.\n",
      "rate_limiting": "Platform rate limits handled:\n- Discord: 50 messages/60 seconds per channel\n- Telegram: 30 messages/second globally\n- Slack: 1 message/second per channel\nQueue strategy: queue excess, retry with backoff.\nMax retries: 3 (configurable).\nBackoff: exponential (300ms, 1s, 5s).\n"
    },
    "access_control": {
      "dm_policy_enforcement": "DM access controlled by dmPolicy:\n- \"pairing\" — device pairing required (most secure)\n- \"allowlist\" — allowFrom[] enforced\n- \"open\" — allowFrom=[\"*\"] required\n- \"disabled\" — all DMs rejected\nCheck at message-routing, before agent dispatch.\n",
      "guild_channel_allowlist": "Guild-level (Discord/Slack):\n- Require mention: @bot mention required (optional)\n- User allowlist: guild.users[]\n- Role allowlist: guild.roles[]\n- Channel allowlist: guild.channels.<id>.allow\nIf allowlist configured: default deny (whitelist mode).\n",
      "permission_checks": "Agent execution permissions:\n- requireMention: @mention required\n- ignoreOtherMentions: drop if others mentioned\n- dangerouslyAllowNameMatching: name match fallback (insecure)\nViolations: message rejected or error sent.\n"
    },
    "message_types": {
      "text_messages": "Plain text or markdown (platform-dependent).\nDiscord: markdown (bold, italic, code blocks).\nTelegram: HTML/Markdown (configurable).\nSlack: mrkdwn format.\n",
      "rich_components": "Types: buttons, select menus, text input, modals.\nButton: label, action, optional payload, style.\nSelect: placeholder, options[], onChange handler.\nModal: title, customId, fields (1-5).\n",
      "reactions": "Actions: add, remove, list.\nDiscord: emoji reactions (custom + unicode).\nTelegram: emoji reactions (limited set).\nSlack: emoji reactions (any Slack emoji).\n",
      "threads": "Thread support (if platform enables):\n- Create thread: send initial message, create context\n- Reply in thread: threadId provided\n- Collapse threads: per session config\n- Inherit from parent: thread inherits DM policy\nCoverage: Discord threads, Telegram topics, Slack threads.\n"
    },
    "moderation_actions": {
      "moderation_capabilities": "Actions for trusted agents:\n- kick: remove from guild/group\n- ban: prevent re-joining (indefinite)\n- timeout: temporary mute (duration configurable)\n- role-add/role-remove: Discord role management\nPermissions: bot must have moderation permissions.\nTrust: admin agent or explicit approval.\n",
      "action_validation": "Moderation actions validated:\n- Target must be guild/group member\n- Bot must have permission\n- Duration constraints: timeout max 28 days\n- Reason logged for audit.\n"
    }
  },
  "events": [
    {
      "name": "message.received",
      "payload": [
        "channel_id",
        "message_id",
        "platform_user_id",
        "message_type",
        "peer_kind"
      ]
    },
    {
      "name": "message.sent",
      "payload": [
        "channel_id",
        "message_id",
        "platform_message_id",
        "delivery_time_ms"
      ]
    },
    {
      "name": "message.failed",
      "payload": [
        "channel_id",
        "message_id",
        "error_code",
        "final_attempt"
      ]
    },
    {
      "name": "platform.connected",
      "payload": [
        "channel_id",
        "account_id"
      ]
    },
    {
      "name": "platform.disconnected",
      "payload": [
        "channel_id",
        "account_id",
        "reason"
      ]
    }
  ],
  "errors": [
    {
      "code": "MESSAGE_NOT_SENT",
      "status": 500,
      "message": "Failed to send message to platform"
    },
    {
      "code": "PLATFORM_RATE_LIMITED",
      "status": 429,
      "message": "Platform rate limit exceeded"
    },
    {
      "code": "DM_NOT_ALLOWED",
      "status": 403,
      "message": "Direct message not allowed for this user"
    },
    {
      "code": "INVALID_MESSAGE_FORMAT",
      "status": 400,
      "message": "Message format invalid for platform"
    },
    {
      "code": "ACCOUNT_NOT_AUTHORIZED",
      "status": 401,
      "message": "Account token invalid or expired"
    },
    {
      "code": "MEMBER_NOT_FOUND",
      "status": 404,
      "message": "Member not found on platform"
    }
  ],
  "states": {
    "message_state": {
      "field": "delivery_state",
      "values": [
        {
          "name": "received",
          "description": "Message received from platform",
          "initial": true
        },
        {
          "name": "routed",
          "description": "Message routed to agent"
        },
        {
          "name": "processing",
          "description": "Agent processing message"
        },
        {
          "name": "responding",
          "description": "Agent response being sent"
        },
        {
          "name": "sent",
          "description": "Response delivered to platform",
          "terminal": true
        },
        {
          "name": "failed",
          "description": "Delivery failed",
          "terminal": true
        }
      ]
    }
  },
  "outcomes": {
    "inbound_message_received": {
      "priority": 1,
      "given": [
        "platform webhook received",
        {
          "field": "message_text",
          "source": "input",
          "operator": "exists"
        },
        "sender verified via platform API"
      ],
      "then": [
        {
          "action": "set_field",
          "target": "message_id",
          "value": "platform message ID"
        },
        {
          "action": "set_field",
          "target": "platform_user_id",
          "value": "extracted from platform"
        },
        {
          "action": "set_field",
          "target": "message_type",
          "value": "determined from content"
        },
        {
          "action": "transition_state",
          "field": "delivery_state",
          "from": "received",
          "to": "routed"
        },
        {
          "action": "emit_event",
          "event": "message.received",
          "payload": [
            "channel_id",
            "message_id",
            "peer_kind"
          ]
        }
      ],
      "result": "Message normalized and routed to agent"
    },
    "message_sent": {
      "priority": 1,
      "given": [
        "platform API accepted message"
      ],
      "then": [
        {
          "action": "set_field",
          "target": "delivery_state",
          "value": "sent"
        },
        {
          "action": "emit_event",
          "event": "message.sent",
          "payload": [
            "channel_id",
            "delivery_time_ms"
          ]
        }
      ],
      "result": "Message delivered to platform",
      "transaction": true,
      "error": "MESSAGE_NOT_SENT"
    },
    "rate_limit_handling": {
      "priority": 2,
      "given": [
        "platform returned 429 or rate limit header"
      ],
      "then": [
        {
          "action": "call_service",
          "service": "queueOutboundMessage",
          "target": "external_service",
          "params": [
            "response_text",
            "retry_config"
          ]
        },
        {
          "action": "emit_event",
          "event": "message.failed",
          "payload": [
            {
              "reason": "rate_limited"
            }
          ]
        }
      ],
      "result": "Message queued with exponential backoff, will retry",
      "error": "PLATFORM_RATE_LIMITED"
    }
  },
  "related": [
    {
      "feature": "openclaw-message-routing",
      "type": "required",
      "reason": "Routes messages to agents"
    },
    {
      "feature": "openclaw-session-management",
      "type": "required",
      "reason": "Stores conversation in persistent session"
    },
    {
      "feature": "openclaw-plugin-system",
      "type": "required",
      "reason": "Channel adapters are plugins"
    },
    {
      "feature": "openclaw-gateway-authentication",
      "type": "required",
      "reason": "Authenticates platform API calls"
    }
  ],
  "sla": {
    "inbound_latency": {
      "max_duration": "2s"
    },
    "outbound_latency": {
      "max_duration": "3s"
    },
    "platform_availability": {
      "target": "99.5%"
    }
  },
  "agi": {
    "goals": [
      {
        "id": "reliable_openclaw_messaging_channel",
        "description": "Platform-agnostic messaging channel integration supporting Discord, Telegram, Slack, and 85+ platforms with unified message routing and delivery",
        "success_metrics": [
          {
            "metric": "success_rate",
            "target": ">= 99.5%",
            "measurement": "Successful operations divided by total attempts"
          },
          {
            "metric": "error_recovery_rate",
            "target": ">= 95%",
            "measurement": "Errors that auto-recover without manual intervention"
          }
        ],
        "constraints": [
          {
            "type": "availability",
            "description": "Must degrade gracefully when dependencies are unavailable",
            "negotiable": false
          }
        ]
      }
    ],
    "autonomy": {
      "level": "supervised",
      "human_checkpoints": [
        "before making irreversible changes"
      ],
      "escalation_triggers": [
        "error_rate > 5"
      ]
    },
    "safety": {
      "action_permissions": [
        {
          "action": "inbound_message_received",
          "permission": "autonomous"
        },
        {
          "action": "message_sent",
          "permission": "autonomous"
        },
        {
          "action": "rate_limit_handling",
          "permission": "autonomous"
        }
      ]
    },
    "tradeoffs": [
      {
        "prefer": "reliability",
        "over": "throughput",
        "reason": "integration failures can cascade across systems"
      }
    ],
    "coordination": {
      "protocol": "orchestrated",
      "consumes": [
        {
          "capability": "openclaw_message_routing",
          "from": "openclaw-message-routing",
          "fallback": "degrade"
        },
        {
          "capability": "openclaw_session_management",
          "from": "openclaw-session-management",
          "fallback": "degrade"
        },
        {
          "capability": "openclaw_plugin_system",
          "from": "openclaw-plugin-system",
          "fallback": "degrade"
        },
        {
          "capability": "openclaw_gateway_authentication",
          "from": "openclaw-gateway-authentication",
          "fallback": "degrade"
        }
      ]
    }
  },
  "extensions": {
    "tech_stack": {
      "language": "TypeScript",
      "patterns": [
        "Adapter pattern",
        "Message normalization",
        "Retry with exponential backoff"
      ]
    }
  }
}