Understanding the DimOS Spec Pattern for Type-Safe RPC Wiring

The DimOS Spec pattern is a Protocol-based interface system that enables automatic, type-safe RPC wiring between modules by detecting Spec-typed attributes during blueprint construction and injecting concrete implementations that satisfy both structural and annotation compliance.

The Spec pattern in the dimensionalOS/dimos repository provides a declarative mechanism for defining RPC interfaces between modules. By inheriting from a special Spec marker Protocol, developers can create type-safe contracts that the blueprint system resolves automatically at build time. This eliminates manual dependency injection while maintaining strict compile-time and runtime type checking across distributed module boundaries.

What Is the DimOS Spec Pattern?

A Spec is a thin Python Protocol that also inherits from the internal Spec marker class defined in dimos/spec/utils.py (lines 22-25). Unlike standard Protocols, Specs serve as explicit interface declarations that the DimOS blueprint system recognizes during module assembly.

When a module declares an attribute typed with a Spec subclass, the system:

  1. Detects the Spec during blueprint construction in _BlueprintAtom.create (lines 95-100 in dimos/core/blueprints.py)
  2. Searches for concrete implementations matching the Spec's method signatures
  3. Validates type annotation compatibility between the Spec and candidate modules
  4. Injects the concrete module instance, enabling transparent RPC calls via the @rpc decorator

This architecture provides static typing through Protocols, runtime safety through compliance checks, and automatic wiring without explicit object passing.

Core Implementation Files

The Spec pattern relies on three primary components across the codebase:

  • dimos/spec/utils.py – Defines the Spec marker Protocol and helper functions is_spec, spec_structural_compliance, and spec_annotation_compliance
  • dimos/core/blueprints.py – Implements the wiring logic through _BlueprintAtom.create and _connect_module_refs (lines 35-78)
  • examples/rpc_calls.py – Demonstrates practical usage with the ComputeSpec example

How the Blueprint System Detects Specs

The Spec Marker Protocol

The foundation resides in dimos/spec/utils.py (lines 22-25), where the base Spec class distinguishes interface Protocols from normal Python Protocols:


# dimos/spec/utils.py

class Spec(Protocol):
    """Marker protocol for DimOS Spec interfaces"""
    pass

The is_spec helper function (lines 27-39) validates that a class is a Protocol, inherits from Spec, and is not the base Spec itself. This check runs during blueprint construction to identify which module attributes require automatic wiring.

Blueprint Atom Creation

During module registration in _BlueprintAtom.create (dimos/core/blueprints.py, lines 95-100), the system scans class annotations. Any attribute where is_spec() returns True becomes a ModuleRef—a placeholder indicating that this module depends on an RPC interface rather than a concrete class.

Module Resolution and Wiring

Structural Compliance Checking

The _connect_module_refs method (lines 35-78 in dimos/core/blueprints.py) performs two-phase validation. First, it checks structural compliance via spec_structural_compliance, verifying that candidate modules implement methods with compatible signatures (name, parameters, and return type compatibility including subclasses).

Annotation Compliance Validation

Second, the system enforces annotation compliance through spec_annotation_compliance. This strict check ensures that type hints in the concrete implementation match the Spec exactly, catching mismatches such as returning list instead of int even when the method signature appears compatible.

Runtime Injection

Once validated, the concrete module is injected into the requesting module's attribute (lines 84-93):


# dimos/core/blueprints.py

setattr(base_module_proxy, module_ref_name, target_module_proxy)

The module reference is stored for reciprocal RPC calls, allowing the client to invoke methods like self.calc.compute1(...) while the @rpc decorator handles the actual remote procedure call.

Complete Code Example

The following example from examples/rpc_calls.py demonstrates the full workflow:


# spec.py – define the interface

from dimos.spec.utils import Spec
from typing import Protocol
from dimos.core.core import rpc

class ComputeSpec(Spec, Protocol):
    @rpc
    def compute1(self, a: int, b: int) -> int: ...

    @rpc
    def compute2(self, a: float, b: float) -> float: ...

# calculator.py – concrete implementation

from dimos.core.module import Module
from dimos.core.core import rpc

class Calculator(Module):
    @rpc
    def compute1(self, a: int, b: int) -> int:
        return a + b

    @rpc
    def compute2(self, a: float, b: float) -> float:
        return a + b

# client.py – request the spec

from dimos.core.module import Module

class Client(Module):
    # Blueprint system injects Calculator automatically

    calc: ComputeSpec

    @rpc
    def start(self) -> None:
        print("c1:", self.calc.compute1(2, 3))   # 5

        print("c2:", self.calc.compute2(1.5, 2.5))  # 4.0

Wiring occurs through blueprint composition:

from dimos.core.blueprints import autoconnect

autoconnect(
    Calculator.blueprint(),
    Client.blueprint(),
).build().loop()

The client module never references Calculator directly—only the ComputeSpec interface—enabling loose coupling with compile-time type safety.

Why It Guarantees Type Safety

The DimOS Spec pattern provides multiple layers of type verification:

  • Static analysis: Because Specs are Protocols, IDEs and type checkers (mypy, pyright) validate method signatures before runtime
  • Structural verification: The spec_structural_compliance check in dimos/spec/utils.py ensures method existence and signature compatibility
  • Annotation matching: spec_annotation_compliance enforces exact type hint equality between Spec and implementation
  • Clear error messages: The blueprint raises descriptive exceptions for ambiguous matches, missing implementations, or annotation mismatches, guiding developers to use .remappings() or correct type hints

Summary

  • The Spec pattern uses a marker Protocol (dimos/spec/utils.py) to declare RPC interfaces between DimOS modules
  • Blueprint construction automatically detects Spec-typed attributes in _BlueprintAtom.create (lines 95-100)
  • Two-phase validation checks structural and annotation compliance before wiring modules together
  • Automatic injection eliminates manual dependency management while maintaining strict type safety
  • The pattern appears in production code at dimos/agents/agent.py and dimos/agents/skills/ for agentic system composition

Frequently Asked Questions

What distinguishes a DimOS Spec from a standard Python Protocol?

A DimOS Spec inherits from both Spec (defined in dimos/spec/utils.py) and typing.Protocol, whereas standard Protocols only inherit from Protocol. The is_spec helper function (lines 27-39) checks for this dual inheritance to identify which interfaces should participate in automatic RPC wiring during blueprint construction.

How does the blueprint system handle multiple modules implementing the same Spec?

The _connect_module_refs method (dimos/core/blueprints.py, lines 35-78) raises an informative error if multiple candidate modules satisfy the Spec's structural and annotation requirements. Developers must then use the .remappings() API to explicitly specify which concrete module should satisfy the Spec interface, preventing ambiguous wiring.

Can Spec methods have different return types in the implementation than declared in the interface?

Structural compliance allows covariant return types (subclasses of the declared return type), but annotation compliance requires exact type hint matches. If the Spec declares -> int but the implementation declares -> float, the blueprint will fail validation even if both are numeric types, ensuring strict type contracts across module boundaries.

Where can I see production usage of the Spec pattern in the DimOS codebase?

Real-world usage appears in dimos/agents/agent.py, where agentic systems declare Spec-typed attributes for skills like navigation and perception. The concrete implementations reside in dimos/agents/skills/, demonstrating how the Spec pattern enables modular, type-safe composition of complex agent behaviors without tight coupling between components.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →