A digital twin of your entire business. And the system of action built on top.
Open Ontology is a platform for modeling your business as a unified knowledge graph. It combines the flexibility of spreadsheets with the query power of databases and the insight of a graph—without the compromises of any single tool.
At its core, every piece of information is stored as a triple: [entity, attribute, value]. This simple model unlocks:
Your business data lives in silos:
| System | What it knows |
|---|---|
| Salesforce | Customers and deals |
| Stripe | Payments and subscriptions |
| Jira | Engineering work |
| Notion | Docs and processes |
| QuickBooks | Finances |
| Spreadsheets | Everything else |
Each system has its own data model, its own API, its own way of thinking about entities. Answering questions that span systems—like "which customers who bought product X also had support tickets mentioning feature Y?"—requires stitching together APIs and hoping the data aligns.
Open Ontology unifies it all.
Triples from different systems coexist in the same graph. The :same-as relationship links entities across sources, enabling unified queries.
Datalog is a declarative query language where shared variables create implicit joins:
This query finds high-value customers with critical support issues—spanning CRM, billing, and support data.
Open Ontology isn't just a database—it's a system of action:
The Open Ontology vocabulary—everything you need to model your domain.
| Term | Description |
|---|---|
| Triple | The atomic unit of data: [entity, attribute, value]. Every fact is a statement about something. |
| Entity | A thing that exists—an employee, a customer, a contract. Identified by a unique string ID. |
| Attribute | A property of an entity, prefixed with : (e.g., :employee:name, :employee:email, :employee:department). |
| Value | The data stored for an attribute. One of six types: string, number, boolean, datetime, ref, json. |
| Ref | A reference value that points to another entity, creating a graph edge. |
| Namespace | An isolated storage context for data. Each namespace has its own SQLite database. |
| Term | Description |
|---|---|
| Object | An entity with a declared type—a structured collection of triples conforming to an Object Type. |
| Object Type | A schema definition describing what attributes and relationships an entity should have. Versioned. |
| Attribute Definition | Specifies an attribute's type, whether it's required, validation rules, and indexing options. |
| Relationship Definition | Defines a connection to another Object Type with cardinality (one or many). |
| Conformance | Whether an entity's actual triples match its declared Object Type schema. |
| Term | Description |
|---|---|
| Link | A first-class relationship between two entities—not just a ref attribute, but an entity itself. |
| Link Type | A schema for links: source type, target type, cardinality, optional properties. |
| Link Instance | An actual connection between two specific entities (e.g., "Alice manages Bob"). |
| Cardinality | How many connections are allowed: one-to-one, one-to-many, many-to-one, many-to-many. |
| Inverse | The reverse direction of a link (e.g., "manages" ↔ "reports-to"). |
| Link Property | Data stored on the link itself (e.g., a "since" date on a "manages" relationship). |
| Term | Description |
|---|---|
| Rule | A declarative Datalog query that detects compliance violations. If the query returns results, those are violations. |
| Violation | A detected instance where an entity fails to meet a rule's requirements. |
| Severity | How critical a violation is: error (must fix), warning (should fix), info (notice). |
| Assignment Strategy | How to route violations to people: by user, role, entity owner, or custom query. |
| Term | Description |
|---|---|
| Task | A unit of work to be completed—can be manually created or auto-generated from violations. |
| Remediation Task | A task created to fix a compliance violation. |
| Task Status | The workflow state: pending, in_progress, completed, cancelled, blocked. |
| Task Priority | Urgency level: critical, high, medium, low. |
| Term | Description |
|---|---|
| Assertion | Adding a new fact (triple) to the store. Immutable once written. |
| Retraction | Marking a fact as no longer active (soft delete via retractedAt timestamp). |
| Time Travel | Querying the state of the database at any historical point in time. |
| Transaction | A group of assertions that share a txId for atomic operations. |
| Term | Description |
|---|---|
| Datalog | A declarative query language using pattern matching and logical variables. |
| Variable | A placeholder in a query, prefixed with ? (e.g., ?person, ?name). |
| Pattern Clause | A triple pattern that matches facts: ["?person", ":name", "?name"]. |
| Predicate Clause | A filter condition: [">=", "?age", 18]. |
| Implicit Join | When the same variable appears in multiple clauses, results are automatically joined. |
| Aggregation | Operations like count, sum, avg, min, max over query results. |
The atomic unit of data. Every fact is a statement: entity has attribute with value.
Organize data by source or domain. Each namespace has isolated storage while allowing cross-namespace references.
Six primitive types for values:
| Type | Example |
|---|---|
string | "Alice Chen" |
number | 42, 3.14 |
boolean | true, false |
datetime | Unix timestamp in ms |
ref | Reference to another entity |
json | Arbitrary nested data |
Every triple is timestamped. Query historical state at any point in time:
The API server exposes RESTful endpoints for all operations:
Open Ontology is built with modern, type-safe technologies:
| Layer | Technology |
|---|---|
| Runtime | Effect-TS for composable, type-safe effects |
| Storage | SQLite with optimized indexes |
| Query | Datalog compiled to SQL |
| API | HTTP with Swagger documentation |
| Frontend | React with React Router |
The architecture is designed for:
Turn your data model into a workflow engine. When data changes, rules fire, tasks get created, people get notified. No integration middleware—the ontology is the system.
Define rules in Datalog, not spreadsheets. Continuous monitoring, automatic violation detection, and full audit trails. Ask "what was our compliance posture on January 15th?" and get an answer.
A database that grows with your application. Start with a sketch of your domain, refine it as you learn. The schema emerges from your data, not the other way around.
Unify your sources without a data warehouse. Import from Salesforce, Stripe, Jira—into one graph. Query across everything. Time travel through changes.
Open Ontology is built on a few core beliefs:
This is the open-source alternative to Palantir Foundry. Your data. Your model. Your rules. Your workflows.
[salesforce/account-123, :account:name, "Acme Corp"][salesforce/account-123, :account:industry, "Technology"][stripe/customer-789, :customer:email, "[email protected]"][stripe/customer-789, :same-as, salesforce/account-123]{ find: ["?name", "?mrr", "?issue"], where: [ ["?customer", ":customer:name", "?name"], ["?stripe", ":same-as", "?customer"], ["?stripe", ":customer:mrr", "?mrr"], [">=", "?mrr", 1000], ["?ticket", ":ticket:customer", "?customer"], ["?ticket", ":ticket:priority", "high"], ["?ticket", ":ticket:title", "?issue"] ]}yield* store.assert({ entityId: "emp:alice", attribute: ":employee:name", value: string("Alice Chen")})yield* namespaces.create("salesforce", "CRM data")yield* namespaces.create("stripe", "Billing data")const pastState = yield* store.queryAsOf( { entityId: "emp:alice" }, new Date("2024-06-15").getTime())import { Effect, Layer } from "effect"import { TripleStore, Datalog, string, number, ref } from "@open-ontology/core"const program = Effect.gen(function* () { const store = yield* TripleStore const datalog = yield* Datalog // Assert facts yield* store.assertBatch([ { entityId: "alice", attribute: ":employee:name", value: string("Alice") }, { entityId: "alice", attribute: ":employee:age", value: number(30) }, { entityId: "alice", attribute: ":employee:department", value: ref("engineering") }, { entityId: "engineering", attribute: ":department:name", value: string("Engineering") } ]) // Query with Datalog const results = yield* datalog.query({ find: ["?personName", "?deptName"], where: [ ["?person", ":employee:name", "?personName"], ["?person", ":employee:department", "?dept"], ["?dept", ":department:name", "?deptName"] ] }) return results // [{ "?personName": "Alice", "?deptName": "Engineering" }]})# Create a namespacecurl -X POST http://localhost:3000/namespaces \ -H "Content-Type: application/json" \ -d '{"name": "demo", "description": "Demo namespace"}'# Assert triplescurl -X POST http://localhost:3000/namespaces/demo/triples \ -H "Content-Type: application/json" \ -d '[{"entityId": "alice", "attribute": ":employee:name", "value": {"type": "string", "value": "Alice"}}]'# Query with Datalogcurl -X POST http://localhost:3000/namespaces/demo/datalog \ -H "Content-Type: application/json" \ -d '{"find": ["?name"], "where": [["?p", ":employee:name", "?name"]]}'