NOETIC
Framework
API Reference

Channel Types

Type definitions for channels, external channels, and channel handles in Noetic.

Channel

A typed communication channel for inter-step message passing.

interface Channel<T> {
  readonly name: string;
  readonly schema: ZodType<T>;
  readonly mode: 'value' | 'queue' | 'topic';
  readonly capacity?: number;
}
FieldTypeRequiredDescription
namestringyesUnique channel name
schemaZodType<T>yesZod schema for message validation
mode'value' | 'queue' | 'topic'yesChannel semantics
capacitynumbernoMaximum buffered messages (for queue/topic modes)

Channel Modes

ModeBehavior
'value'Holds a single value. New sends overwrite the previous value.
'queue'FIFO buffer. Sends enqueue, receives dequeue.
'topic'Pub/sub broadcast. All receivers get every message.

Channel state is keyed by name and lives for the harness lifetime. With a CheckpointStore, value and queue state is checkpointed and restored with each execution that used the channel (CheckpointSnapshot.channels, exported with ChannelSnapshotSchema).

ExternalChannel

An external channel extends Channel with an external flag, enabling cross-process communication.

interface ExternalChannel<T> extends Channel<T> {
  readonly external: true;
}
FieldTypeRequiredDescription
namestringyesUnique channel name
schemaZodType<T>yesZod schema for message validation
mode'value' | 'queue' | 'topic'yesChannel semantics
capacitynumbernoMaximum buffered messages
externaltrueyesMarks channel as externally accessible

ChannelHandle

A handle for sending messages into a channel from outside the agent execution context.

interface ChannelHandle<T> {
  send(value: T): void;
  readonly closed: boolean;
  readonly channel: Channel<T>;
}
FieldTypeDescription
send(value: T) => voidSend a value into the channel. Synchronous — external senders are never back-pressured; at capacity the oldest queued item is dropped and a channel.warning span event (overflow_drop) is recorded
closedbooleanWhether the handle is closed (execution completed)
channelChannel<T>Reference to the underlying channel

getChannelStream

The read-side counterpart to getChannelHandle: subscribe from outside the execution to values the agent sends on an external channel.

harness.getChannelStream<T>(channel: ExternalChannel<T>, executionId: string): AsyncIterable<T>

Delivery is channel-scoped (state is keyed by channel name per harness); executionId bounds only the subscription's lifetime. An id no execution runs under never closes — a harness-lifetime stream ended with iterator.return().

ModeExternal subscriber behavior
queueCompeting consumer — FIFO-fair with internal recv waiters; consuming frees parked senders. Subscribe once per harness
topicNon-lossy tap — per-subscriber buffer (1000, drop-oldest), no pre-subscribe replay
valueCurrent value, then conflated updates; non-consuming

The iterable ends normally when the root execution completes (queue values present at close drain first; later sends stay in the channel) — it never rejects with channel_timeout or cancelled. A re-run or restored root context reopens its id. iterator.return() unsubscribes; the iterable owns a single iterator, so subscribe again for a second consumer.

Context Channel Methods

The Context object provides three methods for channel interaction:

interface Context {
  send<T>(channel: Channel<T>, value: NoInfer<T>): Promise<void>;
  recv<T>(channel: Channel<T>, opts?: { timeout?: number }): Promise<T>;
  tryRecv<T>(channel: Channel<T>): T | null;
}

NoInfer<T> makes the channel alone fix T: sending a plain string to a Channel<'running' | 'done'> is a compile error rather than widening T to string.

MethodDescription
send(channel, value)Send a value to the channel. Resolves immediately unless a queue channel is at capacity, in which case the send parks until a consumer frees a slot (back-pressure): default 30s timeout rejects with channel_timeout; aborting the context rejects with cancelled.
recv(channel, opts?)Receive a value. Blocks until available or timeout (channel_timeout, default 30s). timeout: 0 disables the timeout in every mode and records an unbounded_wait channel warning; a negative timeout rejects with NoeticConfigError code INVALID_CHANNEL_TIMEOUT. Rejects with cancelled when the context is aborted while waiting.
tryRecv(channel)Non-blocking receive. Returns null if no value available.

On this page