---
sidebar_position: 2
title: "The ABI Stack"
---

# The ABI Stack

ABI is organized as open-source Python packages that together constitute an enterprise AI operating system. The runtime layer (`naas-abi-core`) provides the Context Engine, all service port interfaces, and the infrastructure adapters. The application layer (`naas-abi`) adds the built-in agents, the Nexus platform, the base ontologies, and the core module library. The module layer (`naas-abi-marketplace`) extends the system with community-contributed domain modules, all disabled by default and opted in per deployment. `naas-abi-cli` orchestrates the whole stack. Since 3.0, two small packages let modules run in their own process: `naas-abi-sdk`, the async clients and module runtime, and `naas-abi-proto`, the protobuf contracts of the kernel services. All are MIT-licensed Python packages you install and run on your own infrastructure.

The atomic unit of that system is the **module**: a self-contained package that models a domain, ingests data about it, and exposes intelligent capabilities on top. This page walks through how modules are structured, how they fit into the five runtime layers, and what runs in production.

import BrowserOnly from "@docusaurus/BrowserOnly";

---

## Module

A module bundles everything needed to own a domain end-to-end: the ontology that models it, the pipelines and integrations that feed it, and the agents, workflows, and apps that act on it. Think of it as a semantic data and AI product you can enable or disable with a single line in `config.yaml`.

A concrete example: the Account Executive module models sales relationships as OWL entities (Contacts, Accounts, Opportunities), ingests data from Salesforce and LinkedIn via its integrations, runs daily pipelines to keep the knowledge graph current, and exposes a sales agent grounded in your actual CRM data. Unlike a RAG system that retrieves text chunks, it reasons over typed relationships: the agent knows that a Contact works at an Account, that Account is in an Opportunity, and that Opportunity is owned by a specific rep.

The data side defines the domain: `ontologies/` holds OWL/Turtle files that model the knowledge graph schema, `pipelines/` ingests raw data from external sources and converts it into RDF triples, and `integrations/` provides the connectors to those external APIs (GitHub, LinkedIn, Stripe, and others).

The product side exposes capabilities on that data: `agents/` contains LLM-powered agents that reason over the knowledge graph, `workflows/` holds SPARQL-backed tools that agents and users invoke directly, [module jobs](./remote-modules#module-jobs) run scheduled and event-driven work, and `apps/` can surface a web interface, with an API of its own, specific to that module.

Every module declares a `ModuleConfiguration` (merged with global config) and `ModuleDependencies` (the services and other modules it depends on). A module either loads inside the engine, or runs in its own process as a [remote module](./remote-modules) that reaches the engine over NATS. Nothing from `naas-abi-marketplace` loads by default; each module is opted in explicitly.

<BrowserOnly
  fallback={
    <div
      style={{
        height: "400px",
        border: "1px solid #e2e8f0",
        borderRadius: "12px",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        color: "#94a3b8",
      }}
    >
      Loading…
    </div>
  }
>
  {() => {
    const ModuleDiagram = require("@site/src/components/ModuleDiagram").default;
    return <ModuleDiagram />;
  }}
</BrowserOnly>

---

## Architecture

ABI follows a five-layer architecture. The **Interface** layer holds the entry points: the Nexus web app (with its System app for operators), the `abi` CLI, MCP clients, and the SPARQL workbench. The **Application** layer sits below it: the Core API and the Nexus API (one process), the MCP server, and the remote modules, which translate incoming calls into a common internal format and reach the Context Engine.

The **Intelligence** layer is where work happens. The Context Engine wires together services at startup, loads ontologies, and routes requests to the right agent based on intent. The AbiAgent acts as a supervisor: it reads the intent behind each request and dispatches to the right domain agent or marketplace agent. All LLM calls go through the model registry, which serves the models of the enabled provider modules: OpenRouter by default, any other cloud provider module, or Ollama for local and air-gapped deployments. The model can be swapped per agent or per request without rebuilding anything.

The **Services** layer provides the kernel service ports, each with pluggable adapters you can swap via `config.yaml`: a triple store for RDF/OWL knowledge graphs, a vector store for embeddings, object storage for files, datasets, documents, events, a key-value store and cache, secrets, and a message bus for async work. In a NATS deployment the engine serves each of them on the [NATS broker](./nats), so modules in other processes call them the same way. The **Infrastructure** layer backs each port with a concrete Docker service. In local dev most fall back to lightweight file-based alternatives.

<BrowserOnly
  fallback={
    <div
      style={{
        height: "820px",
        border: "1px solid #e2e8f0",
        borderRadius: "12px",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        color: "#94a3b8",
      }}
    >
      Loading…
    </div>
  }
>
  {() => {
    const ArchitectureGraph =
      require("@site/src/components/ArchitectureGraph").default;
    return <ArchitectureGraph />;
  }}
</BrowserOnly>

---

## Packages

The codebase is split into Python packages. `naas-abi-core` is the foundation: the Context Engine, all service port interfaces, and their adapters. It has no agents and no business logic, making it publishable as a standalone library.

`naas-abi` builds on top of it, adding the built-in agents, the Nexus full-stack web app, the Core REST API, and the base ontologies. `naas-abi-marketplace` holds community-contributed modules and agents, all disabled by default and enabled selectively via `config.yaml`. `naas-abi-cli` is the `abi` command-line tool that orchestrates the whole stack. `naas-abi-sdk` and `naas-abi-proto` depend on neither of them: a remote module installs only those two, `protobuf` and `nats-py`, and reaches the engine over NATS.

<BrowserOnly
  fallback={
    <div
      style={{
        height: "380px",
        border: "1px solid #e2e8f0",
        borderRadius: "12px",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        color: "#94a3b8",
      }}
    >
      Loading…
    </div>
  }
>
  {() => {
    const PackageDiagram =
      require("@site/src/components/PackageDiagram").default;
    return <PackageDiagram />;
  }}
</BrowserOnly>

---

## Context Engine

The Context Engine is the runtime core of ABI. It lives in `naas-abi-core` and is responsible for three things: wiring services to their configured adapters at startup, loading and indexing all active module ontologies into a unified knowledge graph, and routing every incoming request to the right agent or workflow based on intent.

When the stack starts, the Context Engine reads `config.yaml`, resolves which service adapters to use (triple store, vector store, object storage, and so on), and loads the ontologies declared by each enabled module. By the time the first request arrives, it has a complete view of the deployed domain knowledge.

At request time, the Context Engine receives a call from the Application layer, determines intent, builds the relevant context from the knowledge graph and enabled modules, and dispatches to the right agent. It does not contain any business logic or domain knowledge itself. Those live in the modules. The Context Engine is the wiring that makes them coherent.

---

## Services

`naas-abi-core` follows a ports-and-adapters (hexagonal) architecture for all infrastructure concerns. Each service is defined as an abstract port interface; concrete adapters implement it. The Context Engine resolves which adapter to use at startup based on `config.yaml`. Swapping the triple store from Fuseki to Oxigraph, or object storage from the file system to S3, requires only a config change with no code edits. In NATS mode each service is also a versioned protobuf contract on the broker (`abi.svc.<service>.v1.*`), and the bus is always NATS JetStream.

<BrowserOnly
  fallback={
    <div
      style={{
        height: "660px",
        border: "1px solid #e2e8f0",
        borderRadius: "12px",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        color: "#94a3b8",
      }}
    >
      Loading…
    </div>
  }
>
  {() => {
    const ServicesDiagram =
      require("@site/src/components/ServicesDiagram").default;
    return <ServicesDiagram />;
  }}
</BrowserOnly>

---

## Data flow

Data enters ABI through integrations: connectors to external APIs such as GitHub, LinkedIn, and Salesforce. Pipelines consume that raw data and convert it into OWL/RDF triples stored in the triple store. Once knowledge is in the graph, it becomes queryable via SPARQL.

When a user or system sends a request, an agent receives it. The agent selects the right workflows and integrations as tools, queries the knowledge graph for context, and executes the business logic. The result travels back through the app layer (REST API, MCP, or Nexus) to the caller.

<BrowserOnly
  fallback={
    <div
      style={{
        height: "340px",
        border: "1px solid #e2e8f0",
        borderRadius: "12px",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        color: "#94a3b8",
      }}
    >
      Loading…
    </div>
  }
>
  {() => {
    const DataFlowGraph = require("@site/src/components/DataFlowGraph").default;
    return <DataFlowGraph />;
  }}
</BrowserOnly>

---

## Production

`abi new project` generates a Docker Compose stack (`abi deploy local`). Start it with `docker compose up -d`, or `abi stack start`. These services come up:

| Service            | Port         | Purpose                                       |
| ------------------ | ------------ | --------------------------------------------- |
| ABI API (`abi`)    | 9879         | The engine, the Core API and the Nexus API    |
| Nexus Web          | 3042         | Next.js frontend                              |
| NATS               | 4222 / 8222  | Broker, JetStream (bus, jobs, discovery) · monitoring (127.0.0.1 only) |
| Fuseki (Jena TDB2) | 3030         | Triple store · SPARQL endpoint                |
| Qdrant             | 6333         | Vector store                                  |
| PostgreSQL         | 5432         | Nexus app data, documents (agent memory, job runs), dataset catalog |
| Redis              | 6379         | Key-value store + cache                       |
| MinIO              | 9000 / 9001  | Object storage + console                      |
| MCP Server         | 8000         | Model Context Protocol (127.0.0.1 only)       |
| Caddy              | 80 / 443     | Reverse proxy · TLS termination               |
| Remote modules     | none         | One service each, in `docker-compose.override.yml` |

RabbitMQ stays in the file behind the Compose profile `rabbitmq`, and Dagster is not in the NATS stack: both are [legacy](/user-guide/build/applications/dagster), kept for projects with NATS off and removed in the next major.

For local development without Docker, `abi dev up` runs the stack as native processes: `nats-server`, an Oxigraph server, the API, Nexus web and the remote modules listed under `dev.modules`, with file-based backends (SQLite, the file system) in place of PostgreSQL, MinIO and Redis.

→ [The Ontology System](./knowledge-graph)
