Skip to content

What is the Reasoning Layer?

The Reasoning Layer is a knowledge representation and reasoning platform. It lets you define structured knowledge (types, data, rules, constraints) and reason over it — deriving new conclusions, answering queries, handling uncertainty, and tracking causality.

If you’ve used databases, rule engines, or logic programming before, the Reasoning Layer sits at the intersection of all three, but with capabilities that go significantly beyond any of them individually.

What problem does it solve?

Most software systems separate data, logic, and types into different layers with different languages:

  • Data lives in a database (SQL, MongoDB)
  • Business logic lives in application code (TypeScript, Python, Java)
  • Type definitions live in schemas (JSON Schema, Protobuf, TypeScript interfaces)
  • Rules live in rule engines (Drools) or workflow systems (Temporal)
  • Uncertainty handling requires separate ML models

This fragmentation means your “knowledge” — what the system knows and how it reasons — is scattered across many places. Changing a business rule might require modifying a database schema, application code, and an ML model.

The Reasoning Layer unifies all of these into a single formalism:

Traditional approachReasoning Layer equivalent
Database table / schemaSort (type in a lattice)
Database row / documentPsi-term (typed feature structure)
Column / fieldFeature (named attribute)
Application logic / rulesInference rules (also Psi-terms)
ML model for uncertaintyFuzzy values and fuzzy inference
Workflow / state machineCognitive agent (BDI architecture)

How it works at a high level

┌─────────────────────────────────────────────────────┐
│ Your Application │
│ (TypeScript / Node.js) │
└────────────────────┬────────────────────────────────┘
│ SDK (this library)
┌─────────────────────────────────────────────────────┐
│ Reasoning Layer Backend │
│ (Rust / Axum) │
│ │
│ ┌──────────┐ ┌───────────┐ ┌────────────────────┐ │
│ │ Sort │ │ Inference │ │ Cognitive Agents │ │
│ │ Lattice │ │ Engine │ │ (BDI Cycles) │ │
│ ├──────────┤ ├───────────┤ ├────────────────────┤ │
│ │ Psi-Term │ │ Fuzzy │ │ Causal │ │
│ │ Store │ │ Reasoning │ │ Reasoning │ │
│ └──────────┘ └───────────┘ └────────────────────┘ │
└─────────────────────────────────────────────────────┘

All computation happens on the server. The SDK handles HTTP requests, serialization, authentication, and TypeScript types. You never write inference algorithms — you declare knowledge and ask questions.

How it compares to things you already know

vs. SQL databases

SQL databases store rows in tables and answer queries with SELECT. The Reasoning Layer stores Psi-terms in a sort lattice and answers queries with unification and inference.

Key differences:

  • Multiple inheritance: A sort can have multiple parents. An employee is both a person and an organization_member. SQL tables don’t support this natively.
  • Rules: You can define logical rules that derive new data automatically. SQL has views and triggers, but not a full inference engine with backward/forward chaining.
  • Uncertainty: Values can be fuzzy (e.g., “temperature is approximately 22°C ± 2°”). SQL values are always exact.
  • Open-world reasoning: The system can say “I don’t know yet” (residuation) instead of treating missing data as NULL or false.

vs. Prolog / logic programming

Prolog is the closest relative. Both use unification and backward chaining. But:

  • Typed feature structures: Psi-terms have named features (like records), not just positional arguments. person(name: "Alice", age: 30) is more readable than person("Alice", 30).
  • Type lattice: Sorts form a lattice with multiple inheritance, GLB, and LUB. Prolog has no built-in type system.
  • Fuzzy logic: Built-in support for fuzzy values and truth degree propagation. Prolog is strictly boolean.
  • Production-grade: RESTful API, multi-tenant, horizontally scalable. Prolog is typically embedded.

vs. OOP class hierarchies

Object-oriented classes and sorts share the idea of inheritance, but:

  • Multiple inheritance without the diamond problem: The sort lattice has well-defined GLB and LUB operations, so multiple inheritance always has a predictable result.
  • Structural matching: You can find all terms that match a pattern, regardless of their exact type. This is like pattern matching across your entire object graph.
  • Logic over iteration: Instead of writing loops to search through objects, you declare rules and goals, and the engine finds solutions.

The six pillars

The Reasoning Layer provides six major capabilities. You can use as many or as few as your application needs:

1. Sorts and Psi-terms

Define a type hierarchy (lattice) and create typed data instances with named features. This is your knowledge base — the “what exists” part.

→ See Sorts and Hierarchy and Psi-Terms and Features

2. Inference (rules and reasoning)

Define logical rules and run backward chaining (goal-directed: “find me all X such that…”) or forward chaining (data-driven: “derive everything that follows from these facts”). This is the “what follows” part.

→ See Inference

3. Fuzzy logic

Handle uncertainty with fuzzy membership functions, truth degrees, and graded similarity. Values don’t have to be exact — they can be “approximately 22” or “probably true with degree 0.8.”

→ See Fuzzy Logic

4. Causal reasoning

Build causal models (directed acyclic graphs), run interventions (“what if I change X?”), and evaluate counterfactuals (“what would have happened if…?”). Based on Judea Pearl’s causal hierarchy.

→ See Causal Reasoning

5. Cognitive agents

Create autonomous agents with beliefs, desires, and intentions (BDI architecture). Agents perceive their environment, form goals, plan actions, and learn from feedback.

→ See Cognitive Agents

6. Optimization

Solve linear programs using the knowledge base as input. Formulate optimization problems directly from your existing data.

→ See Optimization

A minimal example

Here’s the simplest possible end-to-end workflow — define a type, add data, add a rule, and ask a question:

import {
ReasoningLayerClient,
TermInput,
FeatureInput,
guard,
} from '@kortexya/reasoninglayer';
const client = new ReasoningLayerClient({
baseUrl: 'https://platform.ovh.reasoninglayer.ai',
tenantId: 'your-tenant-uuid',
auth: { mode: 'cookie' },
});
// 1. Define a type
await client.sorts.createSort({
name: 'employee',
features: [
{ name: 'name', required: true },
{ name: 'salary', required: true },
],
});
// 2. Add data (facts)
await client.inference.addFact({
term: TermInput.byName('employee', {
name: FeatureInput.string('Alice'),
salary: FeatureInput.integer(120000),
}),
});
// 3. Add a rule: "a high_earner is an employee with salary > 100000"
await client.inference.addRule({
term: TermInput.byName('high_earner', {
name: FeatureInput.variable('?Name'),
}),
antecedents: [
TermInput.byName('employee', {
name: FeatureInput.variable('?Name'),
salary: FeatureInput.constrainedVar('?Salary', guard('gt', 100000)),
}),
],
});
// 4. Ask a question: "who are the high earners?"
const result = await client.inference.backwardChain({
goal: TermInput.byName('high_earner', {
name: FeatureInput.variable('?Name'),
}),
});
for (const solution of result.solutions) {
for (const binding of solution.substitution.bindings) {
console.log(`${binding.variable_name} = ${binding.bound_to_display}`);
// ?Name = Alice
}
}

Next steps