# How the tinychannels Crate Enables OpenHuman's 17 Messaging Channel Integrations

> Discover how the tinychannels crate streamlines OpenHuman's 17 messaging integrations with a unified layer for transport, auth, and data. Simplify your development.

- Repository: [Tiny Humans/openhuman](https://github.com/tinyhumansai/openhuman)
- Tags: deep-dive
- Published: 2026-08-27

---

**The tinychannels crate provides a unified transport, authentication, and data-model layer that allows OpenHuman to support 17 messaging platforms through thin re-exports rather than custom implementations.**

OpenHuman's messaging architecture delegates all platform-specific heavy lifting to the tinychannels crate, a portable Rust library that abstracts Telegram, Discord, Slack, WhatsApp, iMessage, and 12 other services behind a common interface. By treating tinychannels as the single source of truth for channel logic, the `tinyhumansai/openhuman` repository maintains a lean codebase while offering extensive messenger compatibility. This integration pattern reduces adding new providers to a single line of code.

## Architectural Overview of the tinychannels Integration

OpenHuman’s messaging layer lives under `src/openhuman/channels/`. Rather than reinvent transport logic for each service, OpenHuman delegates WebSocket handling, message serialization, OAuth flows, and platform-specific networking to tinychannels, exposing these capabilities through its own domain APIs and RPC endpoints.

### The Channel Trait and Core Abstractions

At the foundation lies the **`Channel`** trait, which defines the minimal API every messenger must implement: `send`, `listen`, and `auth`. OpenHuman re-exports these types directly from tinychannels in [`src/openhuman/channels/traits.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/traits.rs):

```rust
pub use tinychannels::{Channel, ChannelMessage, ChannelSendExt, SendMessage};

```

This re-export strategy ensures that OpenHuman’s interactive loop always uses the upstream trait definitions, guaranteeing consistency across all 17 integrated services.

### Provider Re-exports and Feature Gating

Each of the 17 messaging providers exists as a thin module under `src/openhuman/channels/providers/`. These modules contain no implementation logic; they simply re-export the corresponding tinychannels provider. For example, [`src/openhuman/channels/providers/telegram/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/providers/telegram/mod.rs) contains:

```rust
pub use tinychannels::providers::telegram::{session_store, TelegramChannel};

```

Providers are conditionally compiled behind the `channels` feature flag using `#[cfg(feature = "channels")]` blocks in [`src/openhuman/channels/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/mod.rs). Building without a specific provider omits the corresponding re-export, and the channel runtime gracefully skips absent tools.

### Runtime Host and Relay Infrastructure

The **channel host** supplies the runtime context—storage paths, credential stores, and policy enforcement—that providers require. OpenHuman constructs this host using `tinychannels::host::ChannelHostBuilder` in [`src/openhuman/channels/host/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/host/mod.rs), assembling it once per process and handing it to every provider.

For real-time communication, OpenHuman connects its relay runtime to tinychannels’ transport layer. The file [`src/openhuman/channels/relay_runtime.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/relay_runtime.rs) utilizes `tinychannels::relay::RelayTransport` and `tinychannels::relay::WebSocketRelayConfig` to manage inbound and outbound message envelopes.

## How OpenHuman Implements the 17 Channel Stack

The integration spans seven architectural layers, each delegating to tinychannels:

- **Controllers & RPC**: JSON-RPC endpoints under `/rpc/channels/*` are thin wrappers forwarding calls to tinychannels’ `ChannelManager` (see [`src/openhuman/channels/controllers/ops/connect.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/controllers/ops/connect.rs)).
- **Configuration Schema**: Persistence of tokens and webhook URLs uses tinychannels config types re-exported in [`src/openhuman/config/schema/channels.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/schema/channels.rs).
- **Security Pairing**: OpenHuman’s security model bridges with tinychannels’ session-key handling through `ChannelInboundEnvelope` utilities in [`src/openhuman/channels/host/adapters.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/host/adapters.rs).

All heavy lifting—OAuth flows, platform-specific networking, and message serialization—remains encapsulated within the tinychannels crate.

## Adding a New Messaging Provider

Integrating an additional messenger requires no new logic in OpenHuman. The process follows four steps:

1. **Upstream Implementation**: The tinychannels crate adds a new provider (e.g., `providers::newservice`).
2. **Re-export**: OpenHuman adds a thin module under `src/openhuman/channels/providers/` containing `pub use tinychannels::providers::newservice::NewServiceChannel;`.
3. **Feature Flagging**: The provider is gated behind the `channels` feature in [`src/openhuman/channels/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/mod.rs).
4. **Automatic Exposure**: The `ChannelManager` registered at startup automatically picks up the new provider through the existing RPC controller code.

Thus, the integration effort is reduced to a single line of re-export while tinychannels guarantees consistent behavior across all supported services.

## Working with Channels in Practice

### Sending Messages via the Unified API

OpenHuman exposes a uniform interface for sending messages regardless of the underlying platform. The following example demonstrates sending an email using the shared `ChannelSendExt` trait:

```rust
use openhuman::channels::{Channel, EmailChannel, SendMessage};

// Build the OpenHuman channel host (normally done at startup)
let host = openhuman::channels::host::build_channel_host()?;

// Obtain a concrete channel instance
let email: EmailChannel = host
    .provider_registry()
    .get::<EmailChannel>()
    .expect("Email provider not configured");

// Use the unified ChannelSendExt trait to send a message
let result = email
    .send_message(
        SendMessage {
            to: "user@example.com".into(),
            body: "Hello from OpenHuman!".into(),
            ..Default::default()
        },
    )
    .await?;

println!("Message sent, id: {}", result.message_id);

```

### Listening for Inbound Events

Inbound message handling utilizes the host's unified stream, filtering envelopes by channel type:

```rust
use openhuman::channels::{Channel, ChannelHost};
use futures::StreamExt;

// Assume a host has been built as above
let host: ChannelHost = openhuman::channels::host::build_channel_host()?;

// Subscribe to inbound events from all configured channels
let mut inbound = host
    .inbound_stream()
    .await?
    .filter_map(|envelope| async move { envelope.ok() });

while let Some(envelope) = inbound.next().await {
    println!(
        "Incoming {} message from {}",
        envelope.channel.kind(),
        envelope.sender.id()
    );
}

```

### Cargo Feature Configuration

Providers are toggled via Cargo features. The `channels` feature enables the core runtime, while individual messengers can be selectively included:

```toml
[features]
default = ["channels"]
channels = []                     # core flag

telegram = ["channels"]           # enables TelegramChannel

discord  = ["channels"]           # enables DiscordChannel

```

## Source Code Reference

Key files illustrating the tinychannels integration include:

- [`src/openhuman/channels/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/mod.rs) – Central module re-exporting `Channel`, `ChannelSendExt`, and all provider types.
- [`src/openhuman/channels/traits.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/traits.rs) – Re-exports tinychannels traits for the interactive loop.
- `src/openhuman/channels/providers/*` – Thin wrappers for each tinychannels provider (Telegram, Discord, Email, etc.).
- [`src/openhuman/channels/host/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/host/mod.rs) – Builds the `ChannelHost` using `ChannelHostBuilder`.
- `src/openhuman/channels/controllers/*` – JSON-RPC adapters forwarding to `ChannelManager`.
- [`src/openhuman/channels/relay_runtime.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/relay_runtime.rs) – Connects OpenHuman’s relay to tinychannels’ WebSocket transport.
- [`src/openhuman/config/schema/channels.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/schema/channels.rs) – Re-exports tinychannels configuration types for persistence.

## Summary

- **The tinychannels crate** abstracts all transport, authentication, and messaging logic for 17 platforms, allowing OpenHuman to avoid platform-specific implementations.
- **Architecture**: OpenHuman re-exports traits from [`src/openhuman/channels/traits.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/traits.rs) and providers from `src/openhuman/channels/providers/`, delegating runtime management to `ChannelHostBuilder` and `ChannelManager`.
- **Integration Cost**: Adding a new messenger requires only a single-line re-export in `src/openhuman/channels/providers/` and a feature flag, as all logic resides in the upstream crate.
- **Unified API**: All channels implement the `Channel` trait and `ChannelSendExt`, enabling generic message sending and inbound stream processing regardless of the underlying service.

## Frequently Asked Questions

### What is the tinychannels crate and why does OpenHuman use it?

The tinychannels crate is a self-contained Rust library that implements the full messaging stack—including WebSocket handling, OAuth flows, and platform-specific networking—for 17 different messaging services. OpenHuman uses it to avoid maintaining 17 separate integrations, instead relying on tinychannels as the single source of truth for all messaging functionality.

### How does OpenHuman add support for a new messaging platform?

Adding support requires only a re-export in [`src/openhuman/channels/providers/newservice/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/providers/newservice/mod.rs) that exposes the tinychannels provider type, plus a feature flag in the crate configuration. The existing `ChannelManager` and RPC controllers automatically pick up the new provider without additional logic, as all implementation details live in the tinychannels crate.

### What role does the ChannelHost play in the messaging architecture?

The `ChannelHost`, constructed via `tinychannels::host::ChannelHostBuilder` in [`src/openhuman/channels/host/mod.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/channels/host/mod.rs), supplies the runtime context required by all providers—including storage paths, credential stores, and policy enforcement. It serves as the central registry and execution environment for the 17 integrated messaging channels.

### How are messaging channels configured and enabled in OpenHuman?

Channels are configured through re-exported tinychannels types in [`src/openhuman/config/schema/channels.rs`](https://github.com/tinyhumansai/openhuman/blob/main/src/openhuman/config/schema/channels.rs) and enabled via Cargo features. The base `channels` feature activates the runtime, while individual providers (e.g., `telegram`, `discord`) are toggled as separate features that simply re-export the corresponding tinychannels modules.