Skip to main content

Overview

Channels are NullClaw’s abstraction layer for messaging platforms. Every channel implements the Channel vtable interface, enabling runtime-swappable transport backends.

Channel Interface

Supported Channels (18+)

Real-Time Channels

Webhook-Based Channels

Local/Direct Channels

Channel Message Flow

Inbound Flow

  1. Platform delivers event (webhook POST, WebSocket frame, long-poll result)
  2. Channel implementation parses platform-specific format
  3. Normalizes to ChannelMessage:
  4. Checks allowlist (sender must be in allow_from config)
  5. Routes to agent session via message bus
  6. Agent processes and generates response
  7. Outbound delivery via Channel.send()

Outbound Flow

Channel implementation:
  1. Splits long messages if platform has length limits
  2. Uploads media (if supported)
  3. Formats platform payload (JSON, multipart, etc.)
  4. Sends via platform API (HTTP POST, WebSocket send, etc.)

Configuration

Basic Setup

Channels are configured in ~/.nullclaw/config.json:

Multi-Account Support

Run multiple accounts per channel:

Security: Allowlists

Every channel enforces an allowlist for inbound messages:
  • Empty allowlist = deny all inbound messages
  • "*" = allow all (explicit opt-in)
  • Otherwise = exact-match allowlist (case-insensitive)

Special Cases

Nostr: The owner_pubkey is always allowed regardless of dm_allowed_pubkeys:
Signal: Supports both phone numbers and UUIDs:

Channel-Specific Features

Telegram

  • Long-polling (no webhook setup required)
  • Group support with reply_in_private option
  • Media attachments (photos, documents, audio)
  • SOCKS5 proxy support for restricted regions
  • Inline keyboards (button responses)

Discord

  • WebSocket gateway (real-time events)
  • Thread-aware (creates threads for long conversations)
  • Embed support (rich message formatting)
  • Reaction-based UI interactions
  • Voice channel presence (status only, no audio)

Signal

  • E2E encryption (native Signal protocol)
  • Group chats with privacy mode
  • Attachments (images, files)
  • Typing indicators
  • Requires signal-cli binary in PATH

Nostr

  • NIP-17 gift-wrapped DMs (default)
  • NIP-04 legacy DMs (fallback)
  • Multi-relay rumor deduplication
  • DM inbox relays (kind:10050 announcement)
  • Encrypted private keys (ChaCha20-Poly1305)

WhatsApp

  • Business API (Meta webhook)
  • Template messages (for initial contact)
  • Media support (images, audio, documents)
  • Read receipts

IRC

  • TLS socket connection
  • SASL authentication
  • Channel join/part management
  • PRIVMSG/NOTICE support
  • DCC send (file transfers)

Message Splitting

Channels automatically split messages that exceed platform limits:
  • Respects UTF-8 boundaries (no broken multibyte chars)
  • Configurable max size per platform
  • Iterates chunks for sequential delivery
Default limits:
  • Telegram: 4096 bytes
  • Discord: 2000 bytes
  • IRC: 512 bytes
  • Signal: no enforced limit

Health Checks

Implementations check:
  • Connection state (WebSocket alive, TCP socket open)
  • Authentication status (token valid, login successful)
  • Recent activity (last message sent/received timestamp)

Typing Indicators

Optional vtable methods for real-time UX:
Supported by: Telegram, Discord, Slack, Signal, Matrix.

Streaming Output

Channels can implement sendEvent for incremental delivery:
Supported by: Telegram (edit message), Discord (edit message), Web (WebSocket frames).
Channels without sendEvent fall back to send() for .final stage and ignore .chunk.

Implementation Example

Minimal Channel

Next Steps

Configuration

Full channel configuration reference

Security

Learn about allowlists and pairing