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.

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 (with a warning)
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: T): Promise<void>;
  recv<T>(channel: Channel<T>, opts?: { timeout?: number }): Promise<T>;
  tryRecv<T>(channel: Channel<T>): T | null;
}
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). Rejects with cancelled when the context is aborted while waiting.
tryRecv(channel)Non-blocking receive. Returns null if no value available.

On this page