Skip to main content

What are Channels?

Channels are the communication surfaces through which agents receive work and send responses. They abstract away the specifics of different messaging systems, allowing the same agent to work across CLI, Slack, Discord, and more. In Kubernetes terms, channels are like Services—they define how work reaches your agents.

Channel Architecture

┌──────────────────────────────────────────────────────┐
│                    CHANNELS                           │
├──────────┬──────────┬──────────┬──────────┬─────────┤
│   CLI    │  Slack   │ Discord  │ Telegram │   API   │
└────┬─────┴────┬─────┴────┬─────┴────┬─────┴────┬────┘
     │          │          │          │          │
     └──────────┴──────────┼──────────┴──────────┘


               ┌───────────────────────┐
               │     ORCHESTRATOR      │
               └───────────┬───────────┘


               ┌───────────────────────┐
               │        AGENT          │
               └───────────────────────┘

Supported Channels

Terminal

Interactive command-line interface with styled output
klaw chat

TUI

Beautiful terminal UI with Bubble Tea
klaw chat --tui

Slack

Full Slack integration with thread support
klaw slack

API

REST API for programmatic access
klaw api --port 8080

Channel Interface

All channels implement a common interface:
type Channel interface {
    // Start initializes the channel
    Start(ctx context.Context) error

    // Send delivers a message to the user
    Send(ctx context.Context, msg Message) error

    // Receive waits for and returns user input
    Receive(ctx context.Context) (Message, error)

    // Stop gracefully shuts down the channel
    Stop() error

    // Name returns the channel identifier
    Name() string
}

Message Structure

Messages flow bidirectionally through channels:
type Message struct {
    // Content is the message text
    Content string

    // Role is "user" or "assistant"
    Role string

    // Partial indicates streaming (not complete)
    Partial bool

    // Done indicates the message is complete
    Done bool

    // Metadata contains channel-specific data
    Metadata map[string]string
}

Metadata Examples

Different channels attach different metadata:
{
  "channel": "C0123456789",
  "thread_ts": "1234567890.123456",
  "user_id": "U0123456789",
  "team_id": "T0123456789"
}

Terminal Channel

The default interactive experience:
klaw chat
Features:
  • Styled output with colors and formatting
  • Real-time streaming of responses
  • Tool execution visualization with box drawing
  • Command history
  • Multi-line input support

Simple Mode

For basic terminals without advanced features:
klaw chat --simple

TUI Channel

Rich terminal UI built with Bubble Tea:
klaw chat --tui
Features:
  • Syntax highlighting for code
  • Scrollable message history
  • Progress indicators
  • Keyboard shortcuts
  • Split-pane view

Slack Channel

Full-featured Slack bot integration:
klaw slack

Setup Requirements

  1. Create a Slack app at api.slack.com
  2. Enable Socket Mode
  3. Add bot scopes: chat:write, app_mentions:read, channels:history
  4. Install to workspace
  5. Set environment variables:
export SLACK_BOT_TOKEN=xoxb-...
export SLACK_APP_TOKEN=xapp-...

Thread Support

klaw automatically handles Slack threads:
  • Messages in threads get their own conversation context
  • Main channel messages start new conversations
  • @mention the bot to engage it

Example Interaction

User: @klaw help me debug this error
klaw: I'll help you debug that. Can you share the error message?
User: [shares error in thread]
klaw: [responds in same thread with context preserved]

API Channel

REST API for programmatic access:
klaw api --port 8080

Endpoints

MethodEndpointDescription
POST/v1/chatSend a message and get response
POST/v1/chat/streamStream response with SSE
GET/v1/agentsList available agents
GET/v1/healthHealth check

Example Request

curl -X POST http://localhost:8080/v1/chat \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $API_KEY" \
  -d '{
    "message": "Explain this codebase",
    "agent": "coder"
  }'

Streaming Response

curl -X POST http://localhost:8080/v1/chat/stream \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{"message": "Write a hello world in Go"}'
Response (SSE):
data: {"type": "text", "content": "Here's"}
data: {"type": "text", "content": " a simple"}
data: {"type": "tool", "name": "write", "status": "running"}
data: {"type": "tool", "name": "write", "status": "done"}
data: {"type": "done"}

Channel Bindings

Connect channels to namespaces in distributed mode:
# channel-binding.yaml
apiVersion: klaw.sh/v1
kind: ChannelBinding
metadata:
  name: slack-engineering
  namespace: engineering
spec:
  channel: slack
  config:
    allowed_channels:
      - C0123456789  # #engineering
      - C9876543210  # #deployments
    default_agent: coder
Apply with:
klaw apply -f channel-binding.yaml

Streaming

All channels support real-time streaming:
┌─────────────────────────────────────────────────────┐
│ User Input                                          │
│ > Explain quantum computing                         │
├─────────────────────────────────────────────────────┤
│ Agent Response (streaming)                          │
│                                                     │
│ Quantum computing is a type of computation that█   │
│                                    ↑                │
│                              cursor (typing)        │
└─────────────────────────────────────────────────────┘

Custom Channels

Implement the Channel interface to add custom channels:
type DiscordChannel struct {
    session *discordgo.Session
}

func (c *DiscordChannel) Start(ctx context.Context) error {
    // Initialize Discord connection
}

func (c *DiscordChannel) Send(ctx context.Context, msg Message) error {
    // Send message to Discord
}

func (c *DiscordChannel) Receive(ctx context.Context) (Message, error) {
    // Wait for Discord message
}

Best Practices

In Slack and similar platforms, leverage threading to maintain separate conversation contexts.
Streaming responses show progress and reduce perceived latency.
Always use authentication for API channels in production.
In Slack, limit bot access to specific channels to prevent noise.

Next Steps