Modeling Your Domain

Translate your business domain into a semantic operating model.

An ontology is how you teach the AI to think about your domain. It's the same thing a vendor does when onboarding a customer: explaining what concepts exist, what they mean, why they matter, and how they relate to each other. The difference is that an ontology does this formally, so the AI can use that understanding for any workload: executing processes, exploring data, debugging issues, reasoning over facts from multiple domains, or governing data quality.

This guide covers the thinking behind good domain modeling. Matrices use RDFS for classes, properties, labels, and hierarchies, and SHACL for constraints.

Concept-Oriented Programming

If you're coming from a software engineering background, it helps to think of matrix ontologies as concept-oriented programming. In object-oriented programming, you define classes with methods and the runtime dispatches operations on objects. In a matrix, you define classes with properties and actions, and the AI dispatches operations on concepts.

The parallel is useful:

  • Classes are like types in OOP, but they represent real-world business concepts, not implementation abstractions
  • Properties are like fields, but they form a graph of relationships rather than isolated records
  • Actions are like methods, but they're invoked by the AI as it reasons about what to do, not called directly by application code
  • Shapes are like type contracts or interfaces, defining what valid instances look like
  • Named individuals are like well-known constants or enum values that the AI can reference by name

The key difference is scope. In OOP, your classes model the internals of a single application. In a matrix, your classes model a domain that spans your entire operating model. A workspace can install multiple matrices, and the AI works across all of them as a unified concept space. It's object-oriented thinking applied to business operations rather than code execution.

Start with Your Processes

Don't start by cataloging every concept in your business. Start with the processes and workflows you actually need to operate. What does someone do in your domain? What information do they need? What decisions do they make? What systems do they interact with?

The ontology should model what's needed for those processes. A task management system needs tasks, statuses, assignees, and the actions that create and manage them. It probably doesn't need a full organizational hierarchy unless role-based assignment is part of the process.

This is a pragmatic approach. Every situation is different. Some domains benefit from rich, deeply modeled ontologies because the AI needs to reason over complex relationships. Others work well with a handful of classes and properties because the processes are straightforward. Model what's useful to you.

What an Ontology Teaches

When the AI encounters your domain, it reads your ontology to build a mental model. It learns:

  • What things exist: classes define the types of entities in your domain (tasks, orders, customers, devices)
  • What we know about them: properties describe their attributes and relationships
  • What's valid: SHACL shapes define the constraints and invariants of your data
  • What can be done: actions define the operations available in the domain

This is the same information you'd give a new team member joining your organization. The ontology is the onboarding document for the AI. The better it is, the faster and more effectively the AI can work in your domain.

Classes, Properties, and Individuals

These are the building blocks, and choosing the right one matters for how RARS reasons about your domain.

Classes represent types of things. A task is a class. A customer is a class. Use a class when you're describing a category of entity that can have multiple instances, each with their own identity.

tasks:Task a owl:Class ;
    rdfs:label "task" ;
    skos:definition "A unit of work that can be assigned, tracked, and completed." .

Properties describe facts about things. A task's title is a property. Its due date is a property. There are two kinds:

  • Datatype properties hold literal values (strings, numbers, dates)
  • Object properties reference other entities, creating the graph of relationships
tasks:title a owl:DatatypeProperty ;
    rdfs:domain tasks:Task ;
    rdfs:range xsd:string .

tasks:assignedTo a owl:ObjectProperty ;
    rdfs:domain tasks:Task ;
    rdfs:range people:Person .

Named individuals represent specific, known instances of a class. Use them when your domain has a fixed set of meaningful values that the AI should know about and reason over.

tasks:TaskStatus a owl:Class ;
    rdfs:label "task status" ;
    skos:definition "The lifecycle state of a task." .

tasks:Open a tasks:TaskStatus, owl:NamedIndividual ;
    rdfs:label "open" ;
    skos:definition "Task is ready to be worked on." .

tasks:InProgress a tasks:TaskStatus, owl:NamedIndividual ;
    rdfs:label "in progress" ;
    skos:definition "Task is actively being worked on." .

tasks:Done a tasks:TaskStatus, owl:NamedIndividual ;
    rdfs:label "done" ;
    skos:definition "Task has been completed." .

tasks:Blocked a tasks:TaskStatus, owl:NamedIndividual ;
    rdfs:label "blocked" ;
    skos:definition "Task cannot proceed due to an external dependency." .

Modeling status as named individuals rather than raw strings means the AI understands "blocked" as a specific domain concept with a definition, not just a string it happened to see. It can reason about the set of valid statuses, understand what each one means, and use that in its decision-making.

Whether you need named individuals or simple strings depends on your processes. If the AI just needs to store and display a status, a string is fine. If the AI needs to understand what statuses mean, make decisions based on them, or validate transitions between them, named individuals are worth the effort.

Cross-Domain References

Object properties that reference classes from other matrices are one of the most powerful aspects of semantic modeling. When your task matrix references people:Person, any workspace with both matrices installed gets automatic cross-domain reasoning. The AI can ask "show me all tasks assigned to this person" without custom integration code, because the relationship is declared in the ontology.

# Cross-domain: tasks can be assigned to people from the people matrix
tasks:assignedTo a owl:ObjectProperty ;
    rdfs:domain tasks:Task ;
    rdfs:range people:Person .

These cross-references are what make the workspace a unified concept space rather than a collection of isolated applications. When the AI encounters a people:Person reference while working with tasks, the people matrix activates and its concepts become available. The AI can reason across both domains seamlessly. Your property choices directly shape what the AI knows about during a conversation.

Design for Composition

A matrix is a module, not a monolith. The question to keep asking is: should this be one matrix or several?

Start with the processes. If two processes are independent and rely on different concepts, they belong in separate matrices. A task management matrix and a people directory are separate even though tasks reference people. An order fulfillment matrix and an inventory matrix are separate even though orders consume inventory.

Separating them means:

  • Each can be versioned and deployed independently
  • Workspaces can install one without the other
  • Other matrices can import just what they need

The anti-pattern is stuffing everything into one matrix because "it's all related." In a business, everything is related. The goal is to find natural seams where concepts can stand alone.

Modularity and AI Context

Good modularity directly affects how well the AI reasons about your domain.

For most tasks, RARS works with the conceptual layer of your matrix: class definitions, property schemas, action signatures, and constraints. When a matrix activates, these concepts enter RARS's working context. The more focused that context is, the more precise RARS's reasoning and decision-making.

A well-modeled domain also pays off for RARS's internal capabilities. When something goes wrong, RARS can reason about the full specification for debugging and self-healing. Clear, well-structured models make these capabilities more effective.

Design with these principles in mind:

  • Group by process, not by data: if task management and reporting are independent workflows that share some data, they should be separate matrices. The reporting matrix can import the task matrix's classes without pulling in task management actions.
  • Keep dependency graphs lightweight: when matrix A imports matrix B, B's concepts become available when A activates. If B also imports C, D, and E, activating A cascades. Design imports so that dependencies bring in only what's necessary.

Compare these two designs for the same domain:

Example: Monolithic dependency graph

Everything funnels through a single Operations matrix. Activating Tasks pulls in Operations, which pulls in HR, Inventory, Reporting, and Payroll. RARS's context fills with every concept across the entire business domain.

Example: Modular dependency graph

Each matrix is independent with lightweight cross-references (dotted lines). Activating Tasks only pulls in People (via the assignedTo property). Inventory, Reporting, and everything else stays dormant until the conversation actually needs them.

The modular design gives RARS the smallest effective context for each interaction. A conversation about tasks activates two matrices instead of six.

  • Think about what activates together: RARS activates matrices lazily based on namespace prefixes. If you ask about tasks, only the task matrix activates. If RARS then encounters a reference to people:Person, the people matrix activates too.
  • Annotations are for humans and AI: RARS reads your rdfs:label and skos:definition values to understand what your domain concepts mean. Clear, precise annotations in a focused matrix give both RARS and human readers a strong mental model.

Shapes as Contracts

SHACL shapes define what well-formed data looks like in your domain. They're validated both at assembly time (during build and deploy) and continuously at runtime as data changes. Think of them like compiler diagnostics for your business data: violations surface as errors, warnings, or info-level findings. The platform's validation views show the current state of your data against your shapes, and RARS uses these findings for autonomous data governance, self-correction, and debugging.

tasks:TaskShape
    a sh:NodeShape ;
    sh:targetClass tasks:Task ;
    sh:property [
        sh:path tasks:title ;
        sh:datatype xsd:string ;
        sh:minCount 1 ;
        sh:maxCount 1
    ] ;
    sh:property [
        sh:path tasks:status ;
        sh:class tasks:TaskStatus ;
        sh:minCount 1 ;
        sh:maxCount 1
    ] .

A few things to think about when designing shapes:

  • Required vs optional: use sh:minCount 1 for properties that must exist. Leave out sh:minCount for optional properties.
  • Cardinality: sh:maxCount 1 means single-valued. No sh:maxCount means a property can have multiple values (like tags or dependencies).
  • Value constraints: sh:in restricts to enumerated values. sh:class ensures an object property points to the right type. sh:pattern validates against a regex.
  • Open vs closed: shapes are open by default (sh:closed false), meaning entities can have properties not listed in the shape. This is usually what you want for extensibility.

Payload Classes

When an action creates or updates an entity, the input data is not the same thing as the entity itself. A CreateTaskPayload is not a Task. The payload describes what the caller provides; the task is what exists in the graph afterward.

tasks:CreateTaskPayload
    a owl:Class ;
    rdfs:subClassOf rars-act:Payload ;
    rdfs:label "create task payload" ;
    skos:definition "Input data for creating a new task." .

This separation matters because:

  • The payload may have fewer fields (you don't provide an ID when creating)
  • The payload may have different constraints (some fields are required on create but optional on update)
  • The entity shape evolves independently from the action interface

Annotations

Every class, property, and action should have at minimum a rdfs:label and a skos:definition. These aren't just for documentation. They're how the AI learns what your domain concepts mean. An agent encountering your domain for the first time reads these to understand what actions are available, what the data means, and how to work with it.

tasks:assignee
    a owl:ObjectProperty ;
    rdfs:domain tasks:Task ;
    rdfs:range rars-iam:Principal ;
    rdfs:label "assignee" ;
    skos:definition "The principal assigned to this task." .

Good annotations make your matrix self-describing. Sparse annotations force the AI to guess.

Use rdfs:comment for caveats or context that goes beyond the basic definition. Use skos:scopeNote for usage context. Use skos:example for concrete examples of valid values.

Naming and URIs

Think of URIs as the package structure of your operating model. Just like renaming a package in Java or moving a module in Python forces every consumer to update their imports, changing a URI in your matrix breaks every matrix that references it.

This applies to more than just your spec definitions. When your actions materialize instance data (e.g., creating a tasks:Task with URI https://example.org/tasks/123), those resource URIs become global entities in the workspace. Other matrices can query them, reference them in their own data, and build on them. A resource created by one matrix is visible and usable by any other matrix in the workspace. URI structure for instance data matters just as much as for your ontology.

Conventions from Poliglot's system matrix:

  • Base URI: https://yourdomain.com/spec/matrixname#
  • Classes: PascalCase (tasks:Task, tasks:CreateTaskPayload)
  • Properties: camelCase (tasks:title, tasks:assignedTo, tasks:dueDate)
  • Actions: PascalCase (tasks:CreateTask, tasks:ListTasks)
  • Individuals: PascalCase (tasks:TaskAgent, tasks:Open, tasks:Blocked)

Keep names descriptive but concise. tasks:assignedTo is better than tasks:hasAssignedPerson or tasks:a.

Extensibility

Not everything about your domain is knowable at design time. Workspaces may need to add workspace-specific properties, custom validation rules, or additional actions. Design with this in mind.

  • Keep shapes open unless you have a strong reason to close them
  • Don't over-constrain cardinality on properties that might reasonably have multiple values in some contexts
  • Think about which classes other matrices might want to reference
  • Properties that other matrices might use should have clear, stable domains and ranges

The goal is a model that's complete enough to be useful but not so rigid that extending it requires forking.

Summary

  • Start with processes: model what your actual workflows need, not everything in your domain
  • Teach the AI: the ontology is how the AI learns what things exist, what they mean, and what it can do with them
  • Be pragmatic: every situation is different. Some domains benefit from rich ontologies, others work well with a handful of classes. Do what's useful to you.
  • Use the right building blocks: classes for types, properties for facts, named individuals for known domain values
  • Design for composition: split along natural process boundaries, use lightweight cross-references
  • Shapes validate continuously: they're compiler diagnostics for your business data, at build time and runtime
  • Annotate everything: labels and definitions are how both humans and AI understand your domain
  • URIs are your API: they're stable, meaningful, and part of your contract with other matrices

See Also

On this page