# How DimOS In[T] and Out[T] Streams Enable Inter-Module Communication

> Learn how DimOS In[T] and Out[T] streams enable type-safe inter-module communication using Python type hints for zero-boilerplate publisher-subscriber wiring.

- Repository: [Dimensional/dimos](https://github.com/dimensionalOS/dimos)
- Tags: internals
- Published: 2026-03-15

---

**DimOS In[T] and Out[T] streams provide type-safe, zero-boilerplate inter-module communication by using Python type hints to automatically wire publisher-subscriber relationships, abstracting the underlying transport mechanism for both in-process and distributed execution.**

The dimensionalOS/dimos repository implements a declarative streaming architecture where modules communicate through generic `In[T]` and `Out[T]` type annotations. This design eliminates manual message bus configuration while maintaining strict type safety across process boundaries.

## Type-Safe Stream Declaration

Every DimOS subsystem inherits from the `Module` base class and declares its communication interface using generic type hints. When a module is instantiated, `Module.__init__` inspects these annotations to construct the appropriate stream objects.

In [`dimos/core/module.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/module.py) (lines 22-30), the initialization loop iterates over the class annotations. For each `Out[T]` declaration, the system creates a publish-only stream object; for each `In[T]` declaration, it creates a subscriber-only stream. This happens automatically during construction, requiring no explicit stream initialization code from developers.

## Core Stream Objects

The streaming layer defines distinct objects for publishing and subscribing, each optimized for their specific role.

### Out[T]: The Publisher Interface

Defined at line 139 of [`dimos/core/stream.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/stream.py), the `Out[T]` class maintains a list of local callbacks and holds a reference to a transport object. When `publish()` is called, the `Out[T]` instance invokes `Transport.broadcast` to distribute the message to all connected subscribers, whether they reside in the same process or on remote machines.

### In[T]: The Subscriber Interface

The `In[T]` class, defined at line 13 of [`dimos/core/stream.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/stream.py), manages incoming data reception. It stores an optional `RemoteOut` connection for cross-process communication and provides the `subscribe()` method to register callbacks that process incoming messages of type `T`.

## Transport Wiring and Blueprint Orchestration

Stream objects remain inert until connected to a transport. The `Module.set_transport` method (lines 35-45 of [`dimos/core/module.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/module.py)) attaches a transport implementation—such as LCM, pLCM, or DDS—to a specific stream, enabling actual data flow.

The `Blueprint` class orchestrates system-wide connectivity through `Blueprint._connect_streams` (line 86 of [`dimos/core/blueprints.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/blueprints.py)). This method groups streams sharing the same remapped name and type, creates or reuses the appropriate transport, and injects it into every participating module. This centralized wiring ensures that publishing on one `Out[T]` automatically delivers to every matching `In[T]` across the entire system topology.

## Distributed Communication with Remote Links

When modules execute in separate processes or on different hosts, DimOS transparently bridges the communication gap. The `In` stream’s `connection` field points to a `RemoteOut` proxy object. 

As implemented in [`dimos/core/stream.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/stream.py), `RemoteIn.connect` (lines 55-56) and `In.connect` (line 40) establish this wiring. The remote side publishes through its local transport, while the local side receives data via the `In[T]` subscriber mechanism, making network distribution indistinguishable from local communication in the module implementation code.

## Practical Implementation Example

The following example demonstrates velocity command streaming between two modules:

```python

# my_module.py --------------------------------------------------------------

from dimos.core.module import Module
from dimos.core.stream import In, Out
from dimos.msgs.geometry_msgs import Twist

class CmdPublisher(Module):
    # Outgoing velocity commands

    cmd_vel: Out[Twist]

    def start(self) -> None:
        # Publish a command once per second (demo only)

        import time
        while True:
            self.cmd_vel.publish(Twist(linear=Vector3(x=0.5), angular=Vector3()))
            time.sleep(1)

class CmdConsumer(Module):
    # Subscribe to velocity commands

    cmd_vel: In[Twist]

    def start(self) -> None:
        # Register a callback that runs every time a command arrives

        self.cmd_vel.subscribe(self.handle_cmd)

    def handle_cmd(self, msg: Twist) -> None:
        print(f"Received command: {msg}")

# -------------------------------------------------------------------------

# wiring ---------------------------------------------------------------

from dimos.core.blueprints import autoconnect

# Autoconnect parses the type hints, creates transports, and connects

blueprint = autoconnect(CmdPublisher.blueprint, CmdConsumer.blueprint)
module_coordinator = blueprint.build()

# -------------------------------------------------------------------------

# When the blueprint is built:

# * `CmdPublisher.cmd_vel` gets a transport (e.g. pLCM on topic /cmd_vel)

# * `CmdConsumer.cmd_vel` receives the *same* transport

# * Publishing on the Out side triggers `Transport.broadcast`, which delivers

#   the message to the In side’s subscriber (`handle_cmd`).

```

This implementation functions identically whether both modules run in the same thread or distributed across Docker containers and physical robots, as the `Transport` abstraction handles protocol selection and serialization automatically.

## Summary

- **DimOS In[T] and Out[T] streams** use Python type hints to declare communication interfaces without boilerplate configuration code.
- The `Module` base class automatically instantiates stream objects by inspecting class annotations in [`module.py`](https://github.com/dimensionalOS/dimos/blob/main/module.py).
- **Transport abstraction** allows the same code to operate over LCM, pLCM, DDS, or custom protocols without modification.
- **Blueprint orchestration** automatically wires matching stream pairs and injects shared transport objects.
- **Remote linking** via `RemoteOut` and `RemoteIn` enables transparent cross-process and cross-machine communication.

## Frequently Asked Questions

### How does DimOS ensure type safety between In[T] and Out[T] streams?

DimOS enforces type safety through Python's generic type system during the blueprint wiring phase. The `Blueprint._connect_streams` method validates that matching streams share identical type parameters `T` before establishing the connection, preventing runtime type mismatches that could corrupt data or cause serialization errors.

### Can In[T] and Out[T] streams communicate across different physical machines?

Yes, the streaming layer transparently supports distributed communication. When modules run on separate hosts, the `In[T]` stream connects to a `RemoteOut` proxy that serializes data through the transport layer (such as LCM or DDS), delivering messages across the network without requiring changes to the module's publish/subscribe logic.

### What transport protocols does DimOS support for stream communication?

According to the source code in [`dimos/core/module.py`](https://github.com/dimensionalOS/dimos/blob/main/dimos/core/module.py), DimOS supports multiple transport implementations including LCM (Lightweight Communications and Marshalling), pLCM (Python LCM bindings), and DDS (Data Distribution Service). The specific protocol is selected during blueprint configuration and injected via `Module.set_transport`.

### How does DimOS handle multiple modules subscribing to the same Out[T] stream?

The `Out[T]` object maintains a list of local callbacks and a transport reference. When `publish()` is called, it broadcasts to all registered subscribers through `Transport.broadcast`, which fans out the message to every connected `In[T]` stream regardless of whether they reside in the same process or remote locations, implementing a true publish-subscribe pattern.