<!-- generated by iii-skill-render. DO NOT EDIT (changes here are overwritten on the next render). Edit docs/0-12-0/understanding-iii/channels.mdx. -->
Scanned 9/3/2026
Install to Claude Code
npx -y skills add iii-hq/iii --skill understanding-iii --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Understanding Iii?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/iii-hq-understanding-iii)More formats (shields.io, HTML) on the badges page.
<!-- generated by iii-skill-render. DO NOT EDIT (changes here are overwritten on the next render). Edit docs/0-12-0/understanding-iii/channels.mdx. -->
# Channels
## What channels are
Channels are stream pipes between iii workers. They let one function write bytes while another
function reads those bytes in real time, even when the functions run in different processes or
languages.
Use channels when the data is too large, too binary, or too incremental for a normal JSON function
payload.
## The model
| Concept | What it does |
| ------- | ------------ |
| Channel | A WebSocket-backed pipe managed by the engine. |
| Writer | Sends bytes or text messages into the pipe. |
| Reader | Receives bytes or text messages from the pipe. |
| Ref | A small serializable token passed through `trigger()` payloads. |
The key idea is that refs travel through regular function calls, but the data itself travels over
the channel.
## Why channels exist
Function invocations are JSON messages. That is perfect for structured events and command payloads,
but it is the wrong shape for large files, media, stream responses, and long-running partial output.
Channels split coordination from data transfer:
- A function call coordinates the work.
- A channel carries the stream.
- The engine keeps tracing and routing tied to the same system.
## Runtime flow
```mermaid
sequenceDiagram
participant A as Producer function
participant Engine
participant B as Consumer function
A->>Engine: createChannel()
Engine-->>A: writer, reader, writerRef, readerRef
A->>Engine: trigger B with readerRef
Engine->>B: invoke B with reader ref
A->>Engine: writer sends chunks
Engine->>B: reader receives chunks
A->>Engine: writer closes
Engine->>B: reader ends
```
The producer creates a channel and passes `readerRef` to the consumer. Node and Python materialize
that ref into a live reader before the handler runs. Rust receives the ref as JSON and constructs a
`ChannelReader` from it. The producer writes chunks into its local writer, and the consumer reads
those chunks from its local reader.
## Backpressure and lifecycle
Channel streams connect lazily. Creating a channel allocates refs, but the WebSocket stream connects
when one side starts reading or writing. Backpressure is handled by the SDK stream implementation so
writers can pause when readers cannot keep up.
When the writer closes, the reader receives the stream end. When a worker disconnects, its channel
connections close with it.
For bidirectional communication, create two channels: one for each direction.
## Channels versus triggers
Use a trigger when the payload is a discrete event or command. Use a channel when the payload is a
stream.
| Need | Use |
| ---- | --- |
| Invoke a handler with a small JSON object | Function trigger |
| Serve a file download | Channel |
| Process a large upload | Channel |
| Send progress during a long task | Channel messages |
| Dispatch background work | Queue trigger |
## Related pages
- [How to use channels](../using-iii/channels)
- [Node SDK channels](../sdk-reference/node-sdk#channels)
- [Python SDK channels](../sdk-reference/python-sdk#channels)
- [Rust SDK channels](../sdk-reference/rust-sdk#channels)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!