Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/nearai/ironclaw/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Channels are IronClaw’s abstraction for receiving messages from external sources and sending responses back. They provide a unified interface regardless of the underlying transport (CLI, HTTP, Telegram, web browser).

Architecture

Channel Trait

All channels implement a common interface:
#[async_trait]
pub trait Channel: Send + Sync {
    fn name(&self) -> &str;
    
    async fn start(&self) -> Result<MessageStream>;
    
    async fn respond(
        &self,
        msg: &IncomingMessage,
        response: OutgoingResponse,
    ) -> Result<()>;
    
    async fn send_status(
        &self,
        status: StatusUpdate,
        metadata: &serde_json::Value,
    ) -> Result<()>;
    
    async fn broadcast(
        &self,
        user_id: &str,
        response: OutgoingResponse,
    ) -> Result<()>;
    
    async fn health_check(&self) -> Result<()>;
    
    fn conversation_context(
        &self,
        metadata: &serde_json::Value
    ) -> HashMap<String, String>;
    
    async fn shutdown(&self) -> Result<()>;
}

Message Types

Incoming Message

Unified format for all inbound messages:
pub struct IncomingMessage {
    pub id: Uuid,
    pub channel: String,          // "repl", "telegram", "http", "web"
    pub user_id: String,           // Channel-specific user identifier  
    pub user_name: Option<String>, // Display name
    pub content: String,           // Message text
    pub thread_id: Option<String>, // For threaded conversations
    pub received_at: DateTime<Utc>,
    pub metadata: serde_json::Value, // Channel-specific data
}
Example:
IncomingMessage {
    channel: "repl",
    user_id: "default",
    content: "What's the weather?",
    thread_id: None,
    metadata: serde_json::Value::Null,
}

Outgoing Response

Format for responses back to channels:
pub struct OutgoingResponse {
    pub content: String,                // Response text
    pub thread_id: Option<String>,      // Reply thread
    pub attachments: Vec<String>,       // File paths
    pub metadata: serde_json::Value,    // Channel-specific
}

Status Updates

Real-time activity indicators:
pub enum StatusUpdate {
    Thinking(String),
    ToolStarted { name: String },
    ToolCompleted { name: String, success: bool },
    ToolResult { name: String, preview: String },
    StreamChunk(String),
    Status(String),
    JobStarted { job_id: String, title: String, browse_url: String },
    ApprovalNeeded { request_id: String, tool_name: String, ... },
    AuthRequired { extension_name: String, auth_url: Option<String>, ... },
    AuthCompleted { extension_name: String, success: bool, ... },
}

Built-in Channels

REPL Channel

Interactive command-line interface.
pub struct ReplChannel {
    tx: mpsc::Sender<IncomingMessage>,
    rx: Mutex<Option<mpsc::Receiver<IncomingMessage>>>,
}
Features:
  • Readline support (history, editing)
  • Command completion
  • Multi-line input (Ctrl+D to submit)
  • Status updates (thinking indicators)
  • Color-coded output
Commands:
  • /quit, /exit - Exit IronClaw
  • /clear - Clear conversation
  • /new - Start new thread
  • /undo - Undo last turn
  • /redo - Redo undone turn
  • /jobs - List running jobs
  • /status <id> - Check job status
  • /cancel <id> - Cancel job
  • /interrupt - Stop current operation
  • /compact - Compact conversation history
  • /summarize - Summarize current thread
  • /heartbeat - Run heartbeat check

HTTP Channel

Webhook receiver for external integrations.
pub struct HttpChannel {
    port: u16,              // Default: 3000
    bind_addr: String,      // Default: "127.0.0.1"
}
Endpoints:
POST /webhook HTTP/1.1
Content-Type: application/json

{
  "user_id": "github_webhook",
  "content": "Deploy to production failed: timeout",
  "metadata": {
    "repo": "myorg/myapp",
    "commit": "abc123",
    "severity": "high"
  }
}
Use Cases:
  • CI/CD notifications
  • Monitoring alerts
  • External system events
  • Scheduled jobs (cron)

WASM Channels

Dynamic channel implementations loaded as WebAssembly modules. Architecture:
┌─────────────────────────────────────────────────────┐
│            WASM Channel Runtime                     │
│                                                     │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────┐  │
│  │  Telegram    │  │    Slack     │  │  Signal  │  │
│  │  (telegram.  │  │  (slack.     │  │ (signal. │  │
│  │   wasm)      │  │   wasm)      │  │  wasm)   │  │
│  └──────┬───────┘  └──────┬───────┘  └────┬─────┘  │
│         │                 │                │        │
│         └─────────────────┴────────────────┘        │
│                           │                         │
│                  ┌────────▼─────────┐               │
│                  │  Host Functions  │               │
│                  │  - http_call     │               │
│                  │  - log           │               │
│                  │  - time          │               │
│                  └──────────────────┘               │
└─────────────────────────────────────────────────────┘
Capabilities:
HttpCapability::new(vec![
    EndpointPattern::host("api.telegram.org")
        .with_path_prefix("/bot"),
])
Example: Telegram Channel
1

Build WASM Module

cd channels-src/telegram
cargo build --target wasm32-wasip1 --release
2

Bundle with Runtime

# Automatically bundled during ironclaw build
cargo build --release
3

Configure Bot Token

ironclaw config set TELEGRAM_BOT_TOKEN <your-token>
4

Start IronClaw

ironclaw --enable-telegram
See Telegram Setup Guide for complete integration instructions.

Web Gateway

Browser-based UI with real-time streaming. Transport Protocols:
Purpose: Server-to-client streaming (status updates, tool execution)
const eventSource = new EventSource('/api/chat/stream?session_id=...');

eventSource.addEventListener('thinking', (e) => {
  const data = JSON.parse(e.data);
  showThinkingIndicator(data.message);
});

eventSource.addEventListener('tool_started', (e) => {
  const data = JSON.parse(e.data);
  addToolCard(data.name);
});

eventSource.addEventListener('message', (e) => {
  const data = JSON.parse(e.data);
  appendToResponse(data.content);
});
Event Types:
  • thinking - Agent is processing
  • tool_started - Tool execution began
  • tool_result - Tool output preview
  • message - Response chunk
  • complete - Turn finished
  • error - Error occurred
UI Features:

Chat Interface

  • Multi-threaded conversations
  • Real-time streaming responses
  • Tool execution cards
  • Approval prompts

Memory Browser

  • Search workspace files
  • View/edit documents
  • Daily logs explorer
  • Memory tree view

Job Monitor

  • Live job tracking
  • Container logs
  • Status updates
  • Cancel/retry controls

Extensions

  • Install MCP servers
  • Manage WASM tools
  • OAuth authentication
  • Tool activation

Channel Manager

Coordinates multiple channels and message routing.
pub struct ChannelManager {
    channels: Arc<RwLock<HashMap<String, Arc<dyn Channel>>>>,
}

impl ChannelManager {
    pub async fn start_all(&self) -> Result<MessageStream> {
        // Start all channels and merge streams
    }
    
    pub async fn respond(
        &self,
        msg: &IncomingMessage,
        response: OutgoingResponse,
    ) -> Result<()> {
        // Route response to originating channel
    }
    
    pub async fn broadcast(
        &self,
        channel: &str,
        user_id: &str,
        response: OutgoingResponse,
    ) -> Result<()> {
        // Send proactive message
    }
    
    pub async fn broadcast_all(
        &self,
        user_id: &str,
        response: OutgoingResponse,
    ) -> HashMap<String, Result<()>> {
        // Broadcast to all channels
    }
}
Message Flow:

Conversation Context

Channels provide contextual information for the LLM:
fn conversation_context(&self, _metadata: &Value) -> HashMap<String, String> {
    HashMap::new() // Direct 1:1 session
}
System Prompt Injection:
You are IronClaw, a secure personal AI assistant.

Context:
- Channel: telegram
- Chat Type: group  
- Sender: @alice
- Group: Engineering Team

Guidelines:
- This is a group chat. Be concise.
- Do not share private user context in groups.
- Address @alice specifically in your response.

Broadcasting

Channels support proactive messaging for alerts and notifications. Example: Heartbeat Notification
if let Some(urgent) = heartbeat_result.urgent_items {
    let message = format!(
        "Heartbeat Alert:\n\n{}",
        urgent.join("\n")
    );
    
    channels.broadcast_all(
        "default",
        OutgoingResponse::text(message)
    ).await;
}
Use Cases:
  • Heartbeat urgent items
  • Routine execution results
  • System alerts
  • Self-repair notifications
  • Job completion updates

Thread Management

Channels support multi-threaded conversations.
let msg = IncomingMessage::new("web", "user_123", "Hello")
    .with_thread("thread_abc");
Thread Lifecycle:
  1. Creation: First message in thread
  2. Hydration: Load from database if historical
  3. Updates: Append turns as conversation continues
  4. Persistence: Save to database after each turn
  5. Pruning: Auto-delete stale threads after idle timeout

Custom Channel Development

Build your own channel implementation:
1

Implement Channel Trait

pub struct MyChannel {
    // Your channel state
}

#[async_trait]
impl Channel for MyChannel {
    fn name(&self) -> &str { "my_channel" }
    
    async fn start(&self) -> Result<MessageStream> {
        // Connect to your message source
        // Return stream of IncomingMessage
    }
    
    async fn respond(
        &self,
        msg: &IncomingMessage,
        response: OutgoingResponse,
    ) -> Result<()> {
        // Send response back via your protocol
    }
    
    // ... implement other methods
}
2

Register with ChannelManager

let channel = Arc::new(MyChannel::new());
channel_manager.register(channel).await;
3

Handle Messages

Channel manager automatically:
  • Merges your stream with others
  • Routes responses back to your channel
  • Handles broadcasts
For production channels, consider building as WASM modules for hot-reloading and sandboxing.

Next Steps

Telegram Setup

Configure Telegram bot integration

Web Gateway

Deploy browser-based interface

Webhook Server

Receive events from external systems

WASM Channels

Build custom channels as WASM modules

Build docs developers (and LLMs) love