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 :
REPL Message
Telegram Message
Web Gateway Message
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.
Configuration
Start Server
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 :
HTTP Capability
Secrets Capability
HttpCapability :: new ( vec! [
EndpointPattern :: host ( "api.telegram.org" )
. with_path_prefix ( "/bot" ),
])
Example: Telegram Channel
Build WASM Module
cd channels-src/telegram
cargo build --target wasm32-wasip1 --release
Bundle with Runtime
# Automatically bundled during ironclaw build
cargo build --release
Configure Bot Token
ironclaw config set TELEGRAM_BOT_TOKEN < your-toke n >
Start IronClaw
ironclaw --enable-telegram
Web Gateway
Browser-based UI with real-time streaming.
Transport Protocols :
Server-Sent Events (SSE)
WebSocket
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
Purpose : Bidirectional communication (alternative to SSE)const ws = new WebSocket ( 'ws://localhost:3000/api/ws' );
ws . addEventListener ( 'open' , () => {
ws . send ( JSON . stringify ({
type: 'user_message' ,
content: 'What is the weather?' ,
thread_id: 'thread_123'
}));
});
ws . addEventListener ( 'message' , ( event ) => {
const msg = JSON . parse ( event . data );
switch ( msg . type ) {
case 'assistant_message' :
displayResponse ( msg . content );
break ;
case 'tool_execution' :
showToolStatus ( msg . tool_name , msg . status );
break ;
}
});
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:
REPL Context
Telegram Context
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.
Create Thread
Thread Isolation
let msg = IncomingMessage :: new ( "web" , "user_123" , "Hello" )
. with_thread ( "thread_abc" );
Thread Lifecycle :
Creation : First message in thread
Hydration : Load from database if historical
Updates : Append turns as conversation continues
Persistence : Save to database after each turn
Pruning : Auto-delete stale threads after idle timeout
Custom Channel Development
Build your own channel implementation:
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
}
Register with ChannelManager
let channel = Arc :: new ( MyChannel :: new ());
channel_manager . register ( channel ) . await ;
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