Repository navigation
Architecture
TinyChannels separates channel-specific I/O from OpenHuman-owned runtime behavior. The v2 boundary uses portable typed contracts, while the migration from legacy provider traits is ongoing. The v2 contract specification is normative for wire behavior and explicitly distinguishes implemented surfaces from target behavior.
+----------------------------+
| OpenHuman application |
| config, auth, harness, UI |
+--------------+-------------+
|
v
+----------------------------+
| ChannelBackend |
| connect/status/test/send |
+--------------+-------------+
|
v
+----------------+ +----------------------------+ +----------------+
| Controller UI |------>| ChannelManager |------>| Channel defs |
| setup/status | | validation + delegation | | auth fields |
+----------------+ +----------------------------+ +----------------+
|
v
+----------------------------+
| ProviderContext |
| config + HTTP + host |
+--------------+-------------+
|
+-------------------+-------------------+
| |
v v
+------------------------+ +------------------------+
| Direct providers | | Relay connectors |
| Slack, Discord, etc. | | descriptor + frames |
+-----------+------------+ +-----------+------------+
| |
v v
+------------------------+ +------------------------+
| v2 channel contracts | | Relay action contract |
| typed parts, intent, | | send, passthrough, |
| receipt, capabilities | | inbound ack |
+-----------+------------+ +-----------+------------+
| |
+-------------------+-------------------+
|
v
+----------------------------+
| Delivery queue |
| durability + retry policy |
+----------------------------+
TinyChannels owns portable contracts:
- what a channel message looks like before and after normalization
- what a provider can advertise as capabilities
- what a UI setup definition needs to render auth forms
- what a relay connector sends over the socket
- what durable delivery state means
OpenHuman owns host-specific behavior:
- user accounts and credential storage
- REST/JWT/session authorization
- model and harness execution
- conversation memory and run ledger storage
- event bus fanout and process lifecycle management
The dependency direction is deliberate: providers call small host capability traits, and OpenHuman implements those traits.
Inbound:
platform event
-> provider or relay connector
-> ChannelInboundEnvelope
-> ChannelInboundSink or ChannelHost TurnDispatcher
-> OpenHuman harness turn
-> ChannelOutputEvent stream
Outbound:
agent output or controller send
-> ChannelOutboundIntent
-> durability negotiation
-> provider send or relay send action
-> MessageReceipt
-> delivery ack or retry state
Setup and control:
UI action
-> ChannelManager
-> ChannelDefinition credential validation
-> ChannelBackend implementation in OpenHuman
-> ChannelConnectionResult / ChannelStatusEntry / ChannelTestResult
The crate still supports legacy shapes (ChannelMessage, SendMessage, and raw
controller JSON payloads), but newer code should normalize as early as possible:
- project inbound legacy messages into
ChannelInboundEnvelope - build outbound sends as
ChannelOutboundIntent - carry idempotency keys through
SendMessagewhen using legacy providers - return
MessageReceiptfrom direct adapters where possible
This lets OpenHuman migrate provider by provider without requiring a single large runtime rewrite.
ChannelCapabilities is the v2 descriptor for a configured account. The
legacy static and presentation capability structs are derived projections;
new adapter code should declare the v2 descriptor once. The direct-provider
adapter traits are implemented, but most built-in providers still use the
legacy Channel trait. Treat this as transitional architecture until provider
conformance coverage proves the migration is complete.
Channel and messaging contracts for OpenHuman.
Getting started
Concepts
Modules
Contributing