Domain · Architecture

Nous Domain — Architecture

Nous is a library-only domain — it ships no applications, no standalone services, and no APIs exposed over the network.

14sections13 minread

On this page

Nous - LLM Inference and Reasoning Engine

This document describes the technical architecture of the Nous domain: library organization, module topology, design patterns, data flows, and integration architecture.

Nous is the AI infrastructure backbone of the Oshun monorepo. It answers the question: how do you run large language models, vision models, and audio models on real hardware, at production throughput, without paying per-token cloud API costs or sending user data off-premises? The answer is a carefully layered set of TypeScript libraries that abstract hardware specifics away from every caller. An Iris assistant feature, a Sophia research synthesis pipeline, or a Maya NPC dialogue system all reach Nous through the same interfaces — and Nous figures out whether to run on a GPU, an Apple Neural Engine, or a plain CPU thread pool.

Because Nous ships no services or applications of its own, there is no Nous deployment to operate separately. Domains import @nous/* packages directly and the inference work happens wherever those domains run.


1. Domain Overview#

Nous is a library-only domain — it ships no applications, no standalone services, and no APIs exposed over the network. It is purely a set of TypeScript libraries consumed by other domains and applications in the Oshun monorepo. libs/nous/ holds twenty package directories; nineteen contain implemented source and one (@nous/platform) is a config-only scaffold (no src/).

What Nous provides:

  • A hardware-abstracted ONNX inference runtime, session manager, and model registry (@nous/core)
  • High-throughput inference primitives — batching, KV cache, speculative decoding, multi-GPU parallelism, multi-LoRA serving (@nous/core)
  • An embedding pipeline with multi-modal and multi-provider support, plus similarity search and reranking (@nous/core)
  • Provider-registry-based LLM completion APIs, prompt templates, an agent runtime, and a document-ingestion/RAG surface (@nous/llm)
  • Image and video computer vision — detection, segmentation, OCR, scene understanding, diffusion generation (@nous/vision)
  • Speech, music, and audio analysis (@nous/audio)
  • A model-training surface — distributed training, fine-tuning, preference alignment, diffusion training (@nous/training)
  • Safety classifiers, output enforcement, interpretability, formal verification, and V2 Model Card hosting (@nous/safety)
  • Controllable generative-media packages — image/video control, video object removal, video-to-audio, advanced speech, relighting, portrait animation, joint A/V generation
  • Cooperative-intelligence primitives for the Concordia domain — preference inference, agreement search, bargaining sessions, sealed memory

What Nous does not provide:

  • Network APIs (no REST, WebSocket, or gRPC server)
  • Persistent storage (consuming applications manage storage)
  • Authentication or authorization
  • User-facing applications

2. Design Principles#

These six principles shape every architectural decision in Nous. They explain why the domain is structured the way it is, and what invariants consuming domains can depend on.

  1. Hardware Abstraction — All inference runs behind a unified provider interface. The calling application never writes CUDA-specific or Metal-specific code.
  2. Optional Runtimeonnxruntime-node is an optional dependency. Nous can be imported without installing the GPU runtime (useful in browser/edge environments using the WebGPU provider).
  3. Zero Cloud Lock-In — Every capability in Nous runs locally. No API keys, no external services, no internet required.
  4. Progressive Enhancement — Applications start with CPU inference and add GPU acceleration, batching, and parallelism incrementally as hardware allows.
  5. Composable Primitives — Each module (dynamic-batching, kv-cache, flash-attention, etc.) is independently importable. Applications compose the primitives they need, not a monolithic inference stack.
  6. ESM-First — All three libraries are built as ESM modules for compatibility with modern runtimes (Node.js 22+, browsers via bundlers, Deno, Bun).

3. Technology Stack#

The table below summarises the tooling choices for every @nous/* package. Nothing here is domain-specific configuration — these defaults apply uniformly across all nineteen implemented packages.

Layer Technology
Language TypeScript 5+ (strict mode)
Module format ESM ("type": "module" in every package)
Build @nx/esbuild:esbuild (format: ["esm"], bundle: false)
Package shape Source-only — main/types point at ./src/index.ts
Testing Vitest (@nx/vite:test)
Type checking Explicit typecheck target via tsc --noEmit -p tsconfig.lib.json
Schema validation zod (Concordia packages and some V2 contracts)
Inference backend ONNX Runtime (optional dependency: onnxruntime-node ^1.20.0)

Source-Only Packages and esbuild#

Every libs/nous/*/package.json sets "main" and "types" to ./src/index.ts — packages are consumed directly as TypeScript source through the workspace. The Nx build target uses @nx/esbuild:esbuild with format: ["esm"] and bundle: false, producing unbundled ESM module files so consumers can tree-shake. Each project.json also defines lint, test, and typecheck targets.


4. Library Structure#

libs/nous/ contains twenty package directories. Every implemented package keeps its modules flat under src/ (no nested subdirectories) — each module is a single .ts file with a sibling *.spec.ts, and src/index.ts is a barrel that re-exports every module.

text
libs/nous/
├── core/                     # @nous/core — 84 source modules (flat src/)
├── llm/                      # @nous/llm — 78 source modules
├── vision/                   # @nous/vision — 103 source modules
├── audio/                    # @nous/audio — 81 source modules
├── training/                 # @nous/training — 137 source modules
├── safety/                   # @nous/safety — 64 source modules
├── image-control/            # @nous/image-control — 50 source modules
├── video-control/            # @nous/video-control — 43 source modules
├── video-removal/            # @nous/video-removal — 48 source modules
├── video-to-audio/           # @nous/video-to-audio — 21 source modules
├── advanced-speech/          # @nous/advanced-speech — 31 source modules
├── generative-relighting/    # @nous/generative-relighting — 23 source modules
├── portrait-animation/       # @nous/portrait-animation — 23 source modules
├── joint-av-generation/      # @nous/joint-av-generation — 34 source modules
├── agreement-search/         # @nous/agreement-search — 22 source modules
├── preference-inference/     # @nous/preference-inference — 24 source modules
├── cooperative-bargaining/   # @nous/cooperative-bargaining — 2 source modules
├── concordia-sealed-memory/  # @nous/concordia-sealed-memory — 5 source modules
└── platform/                 # @nous/platform — config-only scaffold (no src/)

@nous/core Module Inventory#

@nous/core is the foundational package. Its 84 modules fall into five functional groups, all residing flat in core/src/:

Runtime and session management — the entry types and runtime (types.ts, runtime-loader.ts, session-manager.ts, inference-engine.ts, model-loader.ts).

Execution providers — one module per hardware backend (cpu-, cuda-, rocm-, metal-, webgpu-, vulkan-, dml-, npu-execution-provider.ts) plus the shared execution-providers.ts registry.

Inference primitives — throughput and memory optimization techniques: dynamic-batching, continuous-batching, llm-serving, speculative-decoding, kv-cache, paged-attention, flash-attention, tensor-parallelism, pipeline-parallelism, model-sharding, moe-parallelism, prefix-caching, radix-attention, prompt-caching, multi-lora-serving, adapter-switching, context-extension.

Generation control — sampling and stopping: streaming-generation, stop-sequences, logit-processors, temperature-sampling, top-k-top-p-sampling, beam-search.

Graph optimization — compile-time improvements: graph-optimization, memory-planning, operator-fusion, quantization.

Model management — the full lifecycle from discovery to eviction: model-registry, model-versioning, model-metadata, model-discovery, model-download, checksum-verification, model-conversion, format-detection, model-caching, model-eviction, model-preloading, warm-model-pool, model-benchmarking, model-profiling, model-optimization-pipeline.

Format readers — direct file format support: safetensors, gguf, ggml, pytorch-loading, tensorflow-loading, jax-loading, tensor.

Embedding and search pipeline — vector generation and retrieval: embedding-generation, text-embeddings, image-embeddings, audio-embeddings, multi-modal-embeddings, embedding-normalization, dimensionality-reduction, batch-embedding, streaming-embedding, embedding-caching, embedding-compression, binary-embeddings, matryoshka-embeddings, similarity-search, approximate-nearest-neighbor, exact-nearest-neighbor, distance-metrics, hybrid-search, reranking, cross-encoder-reranking.

See DOMAINS/nous/specifications.md §10–§19 for the @nous/llm, @nous/vision, @nous/audio, @nous/training, @nous/safety, generative-media, and Concordia module groups.


5. Module Topology#

The diagram below shows how the packages depend on each other. @nous/core is the foundation: it provides the inference engine, providers, and embedding pipeline that all higher-level packages build on. @nous/llm, @nous/vision, @nous/audio, and @nous/training each sit one layer above core, composing its primitives for their respective domains. @nous/safety is a cross-cutting layer that can consume any package. The generative-media and Concordia packages sit at the edges — they wrap specific capabilities without creating circular dependencies.

text
                      @nous/core
                  (84 source modules)
    ┌──────────────────┼──────────────────┐
    |                  |                  |
 Execution         Inference           Model
 Providers         Pipeline          Management
    |                  |                  |
 cpu, cuda,      dynamic-batching,   model-registry,
 rocm, metal,    continuous-batching, model-versioning,
 webgpu, vulkan, speculative-decoding, model-download,
 dml, npu        llm-serving,        checksum-verification,
 (8 modules +    kv-cache,           model-conversion,
 12 known        paged-attention,    format-detection,
 provider        flash-attention,    safetensors, gguf,
 names)              |               ggml, pytorch, …
 Graph                |
 Optimization     Parallelism / Caching / Adapters
    |                  |
 memory-planning, tensor-parallelism,
 operator-fusion, pipeline-parallelism,
 quantization     model-sharding, moe-parallelism,
                  prefix-caching, radix-attention,
                  multi-lora-serving, …
                      |
       ┌──────────────┼───────────────┬─────────────┐
       |              |               |             |
   @nous/llm     @nous/vision    @nous/audio    @nous/training
  (78 modules)  (103 modules)   (81 modules)   (137 modules)
       |              |               |             |
 completion,    detection,      ASR, TTS,      distributed
 agents,        segmentation,   music,         training,
 prompts,       OCR, scene,     audio          fine-tuning,
 reasoning,     diffusion,      analysis       preference
 RAG, NLP       video                          alignment

                @nous/safety (64 modules)
        classifiers, output enforcement,
        interpretability, formal verification,
        V2 Model Card hosting

   Generative-media packages          Concordia packages
   image-control, video-control,      preference-inference,
   video-removal, video-to-audio,     agreement-search,
   advanced-speech,                   cooperative-bargaining,
   generative-relighting,             concordia-sealed-memory
   portrait-animation,
   joint-av-generation

6. nous-core Architecture#

@nous/core implements two interlocking concerns: how a session is acquired and reused (the session manager), and how hardware is selected (provider resolution). Understanding these two flows is the key to understanding how all higher-level Nous packages work.

Inference Session Lifecycle#

The OnnxSessionManager maintains a reference-counted cache of live ONNX sessions. Each entry is keyed by a fingerprint derived from the model source, the resolved provider list, and the session options. When two parts of the application ask for the same model and configuration, they share a single underlying session rather than loading the model twice.

text
Application
    │
    │  sessionManager.acquire({ model, preferredProviders, ... })
    ▼
┌──────────────────────────────────────────┐
│         OnnxSessionManager                │
│                                          │
│  Reference-counted session cache         │
│  (keyed by model fingerprint + providers)│
│  ┌─────────┐ ┌─────────┐ ┌─────────┐    │
│  │ Session │ │ Session │ │  ...    │    │
│  │ refs: 2 │ │ refs: 0 │ │         │    │
│  └─────────┘ └─────────┘ └─────────┘    │
│                                          │
│  On acquire():                           │
│    1. resolveExecutionProviders()        │
│    2. Build cache key; hit → refcount++  │
│    3. Miss → create (dedup in-flight     │
│       creations); evict LRU zero-ref     │
│       entry if cache is full             │
│    4. CPU fallback if primary fails      │
└──────────────────────────────────────────┘
    │
    │  ManagedOnnxSession { session, key, release() }
    ▼
Application runs inference, then release()
    │
    │  (decrements refcount; zero-ref entries
    │   stay cached until LRU eviction)
    ▼
  closeSession(key) releases a zero-ref entry

Provider Resolution Chain#

Before a session can be created, Nous must decide which hardware backend to use. The resolver walks the caller's preferred provider list in order, testing each against the detected hardware environment, and always appends a cpu fallback so the chain can never be exhausted without producing a working session.

text
Preferred providers: ['cuda', 'metal', 'cpu']
                        |
                        v
         Is provider available on this hardware?
                        |
          Yes ──────────┼──────────── No
                        |                |
              Use this provider    Try next in list
                        |                |
                 OnnxRuntime        (fallback loop)
                  .create()               |
                        |         Exhausted all →
                     Session        throw error

7. nous-llm Architecture#

@nous/llm adds two major abstractions on top of @nous/core: a provider-registry pattern for LLM completions (so the calling code never hard-codes a backend), and an agent runtime for orchestrating multi-step reasoning tasks.

LLM Completion Flow#

The completion layer is provider-registry based: callers register ChatCompletionProvider / CompletionProvider implementations on a ChatCompletionAPI / CompletionAPI instance, then dispatch a request. An ONNX-backed provider can compose @nous/core primitives internally — the caller is shielded from that complexity.

text
caller: chatCompletionAPI.complete({ messages, providerId?, ... })
              │
              v
    ┌──────────────────────┐
    │   ChatCompletionAPI   │
    │                      │
    │  1. Select provider  │
    │     (providerId or   │
    │      default)        │
    │  2. Try provider;    │
    │     fall back to     │
    │     fallbackProviderIds │
    │  3. Record latency / │
    │     usage stats      │
    └──────────┬───────────┘
               │  provider.complete(request)
               v
    ┌──────────────────────────────────────┐
    │  ChatCompletionProvider implementation │
    │                                      │
    │  A provider is supplied by the       │
    │  consumer. An ONNX-backed provider    │
    │  may compose @nous/core primitives:   │
    │  OnnxSessionManager.acquire →         │
    │  DynamicBatchScheduler → session.run →│
    │  logit processors / stop sequences /  │
    │  token sampling.                      │
    └──────────┬───────────────────────────┘
               │
               v
       ChatCompletionResponse { choices, usage, latencyMs }

Agent Task Execution Flow#

The agent runtime follows a plan-then-execute model. The planning phase (optional, enabled per agent) translates a high-level goal into an ordered list of concrete steps with a confidence score before any tool is called. The execution loop then steps through those tasks, using memory recall and tool selection to resolve each one.

text
submit(agentId, task)
       │
       v
  ┌─────────────┐
  │ Task Queue  │  (priority-ordered)
  └──────┬──────┘
         │
         v
  ┌─────────────────────────┐
  │   Planning Module       │
  │   (if enabled)          │
  │   - summarize goal      │
  │   - decompose to steps  │
  │   - estimate confidence │
  └──────────┬──────────────┘
             │
             v
  ┌──────────────────────────┐
  │   Execution Loop         │
  │                          │
  │  for each step:          │
  │    1. Recall memory      │
  │    2. Generate action    │
  │    3. Select tool        │
  │    4. Execute tool       │
  │    5. Store result       │
  │    6. Update state       │
  │                          │
  │  On error:               │
  │    - retry with backtrack│
  │    - emit failure event  │
  └──────────┬───────────────┘
             │
             v
  TaskResult { state, output, steps }

8. nous-vision Architecture#

@nous/vision builds on the same @nous/core session infrastructure as the LLM stack, but adds vision-specific pre- and post-processing steps: image buffers are resized, normalised, and tensor-encoded before inference, and raw model outputs are decoded through non-maximum suppression, mask decoding, or text parsers depending on the task.

Standard Vision Inference Pipeline#

text
Input Image (Buffer | ImageData)
        │
        v
  ┌──────────────────┐
  │  Image Preprocess│
  │  - resize        │
  │  - normalize     │
  │  - tensor encode │
  └────────┬─────────┘
           │
           v
  ┌──────────────────┐
  │  Model Session   │  (@nous/core session-manager)
  │  Provider:       │
  │  cuda/metal/cpu  │
  └────────┬─────────┘
           │
           v
  ┌──────────────────┐
  │  ONNX Inference  │
  │  (run)           │
  └────────┬─────────┘
           │
           v
  ┌──────────────────┐
  │  Output Decode   │
  │  - postprocess   │
  │  - NMS (detect.) │
  │  - decode masks  │
  │  - parse text    │
  └────────┬─────────┘
           │
           v
   Typed result object

Diffusion Pipeline#

Image generation with Stable Diffusion or Flux requires a multi-stage pipeline that interleaves a text encoder, a noise scheduler, many denoising iterations through a UNet, and a final VAE decode. Nous models each stage as a separate ONNX session so the hardware provider can be selected per stage.

text
text prompt
    │
    v
┌─────────────────────────────────┐
│       Diffusion Pipeline        │
│                                 │
│  1. Text Encoder (CLIP)         │
│     prompt → conditioning       │
│                                 │
│  2. Scheduler Init              │
│     noise schedule, timesteps   │
│                                 │
│  3. Denoising Loop (N steps)    │
│     ┌────────────────────────┐  │
│     │  UNet forward pass     │  │
│     │  (ONNX session)        │  │
│     │  predict noise         │  │
│     │  scheduler step        │  │
│     └────────────────────────┘  │
│                                 │
│  4. VAE Decode                  │
│     latent → pixel image        │
│                                 │
└─────────────────────────────────┘
           │
           v
      Buffer (PNG/JPEG)

9. Key Design Patterns#

The following patterns recur across all @nous/* packages. A new engineer implementing a feature or a new provider should follow them to stay consistent with the existing codebase.

Provider Interface Pattern#

Provider names are an open union (OnnxExecutionProviderName). resolveExecutionProviders ranks a requested list against detected hardware and always appends a cpu fallback; OnnxSessionManager.acquire takes a NousOnnxSessionConfig and never needs backend-specific calling code. The calling site looks like this regardless of whether the runtime machine has a GPU:

typescript
// Calling code — no CUDA-specific logic
const managed = await sessionManager.acquire({
  model: modelPathOrBytes,
  preferredProviders: ['cuda', 'metal', 'cpu'], // priority list
  allowProviderFallback: true,
});
const outputs = await managed.session.run(feeds);
await managed.release();

Optional Dependency Pattern#

runtime-loader.ts loads onnxruntime-node lazily and throws a typed error when it is absent, so @nous/core compiles without the native runtime. This is what enables @nous/core to be imported in browser or serverless targets that cannot install a native binary — the error is only thrown at the moment inference is actually attempted:

typescript
// libs/nous/core/src/runtime-loader.ts (shape)
export async function loadOnnxRuntime(
  options: OnnxRuntimeLoaderOptions = {}
): Promise<OnnxRuntimeModule> {
  const runtimePackage = options.runtimePackage ?? 'onnxruntime-node';
  try {
    const candidate = await (options.load ?? defaultRuntimeLoader)(
      runtimePackage
    );
    return resolveOnnxRuntimeModule(candidate); // validates Tensor + InferenceSession
  } catch (error) {
    if (isMissingModuleError(error, runtimePackage)) {
      throw new OnnxRuntimeNotAvailableError(runtimePackage, error);
    }
    throw error;
  }
}

Composable Pipeline Pattern#

Rather than a single monolithic inference class, consumers assemble a pipeline from the specific primitives they need. A high-throughput serving setup might combine a dynamic batch scheduler, a KV cache manager, and tensor parallelism; a lightweight edge deployment might use only the session manager:

typescript
// Consumer assembles their own pipeline
const batcher = new DynamicBatchScheduler(engine, {
  maxBatchSize: 16,
  maxQueueDelayMs: 8,
});
const kvCache = new KvCacheManager({
  maxTotalBytesReserved: 512 * 1024 * 1024,
});
const cache = kvCache.allocate({
  modelId: 'llama-3-8b',
  layerCount: 32,
  numHeads: 32,
  headSize: 128,
});

Agent Event Sourcing Pattern#

The AgentArchitecture runtime (libs/nous/llm/src/agent-architecture.ts) records typed AgentRuntimeEvents as agents and tasks transition through their lifecycle states. The event log is queryable for replay, debugging, and monitoring. Because every state change is recorded as an event (not mutated in place), the full history of an agent run is always recoverable:

typescript
// Query the runtime event log
const events = agentRuntime.getEvents(100); // last 100 events
const stats = agentRuntime.getStats(); // AgentArchitectureStats

// Agent lifecycle: stopped | idle | running | paused | error
// Task lifecycle:  queued | running | completed | failed | cancelled | timeout

10. Data Flow Diagrams#

Embedding Generation Flow#

Embeddings are the bridge between raw text or media and vector search. The EmbeddingGenerator abstracts multiple providers (a local sentence-transformer, an OpenAI embedding endpoint, a Cohere model) behind a single interface, routing by modality and falling back across providers on failure.

text
Application
    │  generate({ modelId, input: { content, modality: 'text' } })
    ▼
┌──────────────────────────────┐
│      EmbeddingGenerator      │
│                              │
│  1. Select provider          │
│     (by id / priority +      │
│      supported modality)     │
│                              │
│  2. Call provider.generate() │
│     fall back on failure     │
│                              │
│  3. Truncate to              │
│     outputDimensions         │
│  4. Record provider stats    │
└──────────────┬───────────────┘
               │
               v
   EmbeddingGenerationResult { vector, dimensions, ... }

RAG Pipeline Flow#

RAG (Retrieval-Augmented Generation) grounds an LLM response in specific documents by retrieving relevant passages and injecting them into the context window. The pipeline runs through five stages: embedding the query, searching the vector index, reranking candidates with a cross-encoder, building an injection context, and finally calling the LLM with that context attached.

text
Query: "What is the refund policy?"
               │
               v
    ┌────────────────────┐
    │  Query Embedding   │  (EmbeddingGenerator)
    └────────┬───────────┘
             │ vector
             v
    ┌────────────────────┐
    │  Vector Index      │  (hybridSearch)
    │  search(topK=5)    │
    └────────┬───────────┘
             │ SearchResult[]
             v
    ┌────────────────────┐
    │  Reranker          │  (cross-encoder)
    └────────┬───────────┘
             │ reranked SearchResult[]
             v
    ┌────────────────────┐
    │  Context Builder   │
    │  chunk[0..k] →     │
    │  injected context  │
    └────────┬───────────┘
             │
             v
    ┌────────────────────┐
    │  LLM Completion    │
    │  (with RAG context)│
    └────────┬───────────┘
             │
             v
        Grounded response

11. Deployment Characteristics#

Runtime Environments#

Nous supports a wide range of deployment targets. The runtime environment determines which execution provider is selected; no code changes are needed between targets — only the hardware and the installed ONNX Runtime variant differ.

Environment Provider Used Notes
NVIDIA GPU server cuda Requires CUDA 12.x and onnxruntime-node
AMD GPU server rocm Requires ROCm 5.6+ and onnxruntime-node
macOS (Apple Silicon) metal Metal acceleration via onnxruntime-node
Windows desktop dml DirectML via DirectX 12
Browser (WebGPU) webgpu Uses onnxruntime-web, not onnxruntime-node
Any CPU cpu Universal fallback, no GPU drivers needed
Serverless/edge cpu Use quantized models (INT8/INT4) for size

WASM Considerations#

When bundling @nous/core for browser use (e.g., in a PWA), use webgpu or cpu providers. The onnxruntime-web package includes WASM binaries. The metal, cuda, and rocm providers are Node.js-only.

Memory Sizing Guidelines#

Model memory requirements grow with parameter count and numerical precision. The table below gives approximate VRAM floors for common configurations — the actual requirement depends on the KV cache allocation on top of these weights.

Model Size Min GPU VRAM Recommended Config
7B (FP16) 14 GB Single GPU, no parallelism needed
7B (INT4) 4 GB Single GPU with quantization
13B (INT8) 13 GB Single GPU or 2-GPU tensor parallelism
70B (INT4) 40 GB Multi-GPU tensor parallelism (2× 24 GB or 4× 12 GB)

Package Entry Points#

@nous/core (and every other @nous/* package) is a source-only workspace package — package.json sets main and types to ./src/index.ts and declares "type": "module". There is no exports map and no published dist/; the Nx build target emits unbundled ESM to libs/nous/<pkg>/dist only when explicitly run. Consumers resolve @nous/* through the tsconfig.base.json path mapping "@nous/*": ["libs/nous/*/src/index.ts"]. The Concordia packages (@nous/agreement-search, @nous/cooperative-bargaining, @nous/preference-inference, @nous/concordia-sealed-memory) additionally declare an explicit exports field pointing at ./src/index.ts.


12. Domain Dependencies#

External Dependencies#

The only external runtime dependency is onnxruntime-node, and even that is optional. Nous deliberately avoids third-party service dependencies at the library level — consuming applications wire in any external providers (such as an OpenAI embedding endpoint) through the provider registration interfaces.

Dependency Type Notes
onnxruntime-node Optional Core inference backend. Not required in browser environments using webgpu.

Domains That Depend on Nous#

Each consuming domain uses Nous for a different purpose, which is why the boundary is clean: Nous knows nothing about Iris assistant UX, Sophia research workflows, or Maya world generation. It exposes primitives; the consuming domain decides what to do with them.

Domain Libraries Used How Nous Is Consumed
Iris @nous/core, @nous/llm Local LLM serving for privacy mode; embedding generation for knowledge base and memory
Sophia @nous/llm LLM reasoning for research synthesis
Psyche @nous/vision Facial emotion recognition and perception models
Maya @nous/llm NPC dialogue generation and world content AI

Cross-Domain Dependencies Within Nous#

Most @nous/* packages are self-contained — they bring only devDependencies and depend on nothing outside the package at runtime. The two exceptions exist for concrete architectural reasons:

  • @nous/safety depends on @kalika/core and @kalika/formal-verification because formal safety verification requires the Kalika theorem-prover runtime. The safety invariant proofs are not a Nous concern to implement from scratch; they delegate to Kalika's proven core.
  • The three Concordia packages (@nous/preference-inference, @nous/agreement-search, @nous/cooperative-bargaining) depend on @concordia/contracts because they implement the computational half of a bargaining session — the preference models and search kernels — while Concordia owns the type contracts that describe parties, cases, and outcomes. Nous cannot define those contracts without creating a circular dependency, so it consumes them from @concordia/contracts instead.
@nous package Workspace dependency
@nous/safety @kalika/core, @kalika/formal-verification
@nous/preference-inference @concordia/contracts
@nous/agreement-search @concordia/contracts
@nous/cooperative-bargaining @concordia/contracts

13. Concordia Cooperative-Intelligence Packages#

Four @nous/* packages provide reusable cooperative-intelligence primitives consumed by the Concordia domain (DOMAINS/concordia). These packages sit at the intersection of Nous and Concordia: Nous owns the algorithms (utility model fitting, multi-objective optimisation, privacy primitives), while Concordia owns the policy (legal boundaries, settlement authority, user experience). The boundary exists precisely so that the algorithms can be tested, versioned, and reused independently of any specific dispute or governance domain.

Data that crosses the boundary: @concordia/contracts types for parties, cases, and outcomes flow into Nous as inputs to the preference and search kernels. Calibrated utility estimates and Pareto-frontier candidate agreements flow out to Concordia as results. No settlement decisions, legal boundaries, or product UX logic cross into Nous.

Package Architectural role
@nous/preference-inference Pairwise preference elicitation and five calibrated utility-model estimators (Bradley-Terry, Thurstone-Mosteller, Plackett-Luce, Gaussian-process, neural ranker); calibration, fairness metrics, BATNA analysis
@nous/agreement-search Search-kernel registry plus seven search kernels (Nash genetic, NSGA-II, MAP-Elites, MCTS/LATS, CP-SAT, Bayesian optimization, PSRO) and a coalition-stability search; candidate generation and clause mutators
@nous/cooperative-bargaining Session-scoped bargaining substrate bridging @concordia/contracts and the search kernels (phase machine, stakeholder registry, budget)
@nous/concordia-sealed-memory Privacy primitives — envelope-encrypted sealed-memory store, zero-retention routing/attestation, confidential-compute scoring

These packages provide reusable preference/search/bargaining/privacy primitives only. Domain policy, legal boundaries, settlement authority, and user experience are owned by the Concordia domain and its peer domains (Themis, Kuanyin, Maat, Aje, and others).


Document Provenance#

This architecture document was written against the source under libs/nous/. Package inventory and module counts come from ls libs/nous/ and the src/index.ts barrels; the dependency table is read from each libs/nous/*/package.json; build targets from each project.json. It describes the AI-infrastructure module topology, the inference/LLM/vision/audio architecture, execution providers, session/model/inference/embedding/search/ agent/document pipelines, deployment characteristics, and the cross-domain and Concordia dependency structure.