What an Ontology Actually Is Two dashboards at the same company report churn for the same quarter as 4.1 percent and 6.8 percent, both correct because each uses a different definition of churn that exists only in analysts' heads, not in any machine-readable form. This is the first part of a five-part series that builds a governed layer of meaning, starting with writing one churn rule into a file a machine can read, and it explains that an ontology, as defined by Tom Gruber in 1993, is an explicit specification of a conceptualization, distinguishing it from a taxonomy by including relationships and rules. Ontology 101, Part 1 of 5: A hands-on series that starts at first principles and ends at Databricks Genie Ontology. Each part ends with a working artifact you carry into the next. Two dashboards at the same company report churn for the same quarter. One says 4.1 percent. The other says 6.8 percent. Both are correct. One counts an account as churned when the subscription lapses. The other counts it when usage drops to zero for thirty days because the sales team argues that a lapsed contract with active users is a renewal conversation, not a loss. Neither definition is written down anywhere a machine can read. Both live in the heads of the analysts who built the dashboards, one of whom left in March. Now put an AI agent in front of that warehouse and ask it, "What's our churn?” It will pick one, confidently. It might even pick a third definition, inferred from a column named churn flag whose population logic nobody remembers. This series builds a governed layer of meaning between the question and the query, using one SaaS churn example throughout. Part 1 writes one churn rule into a file a machine can read. Keep that file. The later parts only make sense if it exists. Each part is one idea plus a lab. You carry the same domain forward. "Ontology" comes from the Greek "ontos," meaning "being," and "logia," meaning "study." Aristotle never used the word. In the categories, he listed ten kinds of things that can be said of a subject, e.g., substance, quantity, quality, and relation. Later writers, starting with Porphyry, drew those kinds as trees that nest. The word itself arrived around 1606, in Jacob Lorhard’s Ogdoas scholastica . Christian Wolff’s Philosophia prima sive ontologia 1730 made it a standard name for the study of being. For three centuries it stayed a philosopher’s word. Then computer science took it. In 1993, Tom Gruber https://tomgruber.org/writing/definition-of-ontology needed a term for something knowledge engineers kept building. They wanted a formal description of what exists in a domain, written so software systems could share it. Gruber’s definition became the field’s default. An ontology is an explicit specification of a conceptualization. Every word in that definition does work. Conceptualization is the abstract model in someone’s head, e.g., the sales team’s idea of what “churned” means. "Specification" means written down, not tribal knowledge. "Explicit" means the meaning is stated, not implied by a column name. The 4.1 versus 6.8 problem is, in Gruber’s terms, two conceptualizations and zero specifications. People often mix the word with taxonomy. A taxonomy lists kinds and subkinds. An ontology also states relationships and rules, e.g. every subscription belongs to one account, and an account with no active subscription is churned. The rules have to live in the file. A query that restates them is still a query. Between Aristotle and Gruber sits a stretch of AI history you should know, mostly because later parts of this series reuse it under new names. Frames Marvin Minsky, mid-1970s packaged knowledge into named objects with slots and default values. A frame for “restaurant visit” has slots for menu, table, and bill. A JSON schema with inheritance describes the same shape. Description logics starting with Ron Brachman’s KL-ONE, late 1970s made the semantics formal. A description logic is a decidable fragment of first-order logic built for this job. It defines classes, properties, and constraints so that a machine can prove consequences. If every enterprise subscription is a paid subscription and Acme’s subscription is enterprise, the machine derives that Acme pays. It does not look up the facts. It proves the fact from the definitions. Description logics became the mathematical foundation of OWL, which you will write into the file below, and which Part 4 will run on Databricks. Then there is Cyc . Doug Lenat started it in 1984 with the goal of hand-coding common sense into one knowledge base. Forty years and tens of millions of rules later, Cyc had proved its premise and disproved its method. Machines need explicit knowledge to reason reliably. Humans should not type all of it in. Hold that thought until Part 5. There you will write some of the model by hand, and the platform will also learn a model from tables, queries, and dashboards. Genie Ontology is the learned layer. It is not the OWL file you are about to build. In 2001, Tim Berners-Lee published a vision of a web where data carried machine-readable meaning. The Semantic Web mostly did not happen, and Part 2 covers why. People still use the W3C standards built for that project, including inside modern data platforms. Those standards are also the simplest way to make Gruber’s definition concrete. There are four pieces. RDF is the data model. Everything is a triple: subject, predicate, object. A pile of triples is a graph, and that is the whole data model. Any fact, from any source, decomposes into the same shape, which is why triples outlived the larger project. RDFS adds vocabulary for structure. You get classes, subclasses, and property domains and ranges. This layer is the taxonomy. OWL adds the logic, backed by description logics. You can state that a property takes at most one value, that two classes cannot overlap, and that a class is defined by a condition. The OWL layer is where a taxonomy becomes an ontology. SPARQL is the query language. It matches patterns over triples. If you know SQL, the SELECT / WHERE shape will look familiar. You can write useful queries in it within about ten minutes. That covers the concepts. Now open a terminal. The running example for this whole series is a B2B SaaS business: accounts, subscriptions, plans, users, usage events, support tickets, and churn. In later parts the example becomes real tables in Unity Catalog, a knowledge graph in Neo4j, governed metrics, and a Genie space. Today it becomes an ontology, and the first step is paper. Write down the things in the domain, not the tables you would eventually store them in. Now the relationships, as sentences: And two rules, the kind that have to live in the file rather than in a dashboard: Every one of those sentences is a triple or a constraint. The paper exercise is the ontology. Everything after this is transcription. You need Python and one package: pip install rdflib Define the vocabulary. Classes first: python from rdflib import Graph, Namespace, Literal, RDF, RDFS, OWL, XSDSAAS = Namespace "http://example.org/saas " g = Graph g.bind "saas", SAAS g.bind "owl", OWL Classes: the kinds of things that existfor cls in "Account", "Subscription", "Plan", "User", "SupportTicket" : g.add SAAS cls , RDF.type, OWL.Class Taxonomy: paid plans are plansg.add SAAS.PaidPlan, RDF.type, OWL.Class g.add SAAS.PaidPlan, RDFS.subClassOf, SAAS.Plan g.add SAAS.FreePlan, RDF.type, OWL.Class g.add SAAS.FreePlan, RDFS.subClassOf, SAAS.Plan print f"{len g } triples so far" Then the relationships. In OWL, relationships between things are object properties, and attributes with literal values are datatype properties: Object properties: thing-to-thing relationshipsprops = "hasSubscription", SAAS.Account, SAAS.Subscription , "onPlan", SAAS.Subscription, SAAS.Plan , "belongsTo", SAAS.User, SAAS.Account , "filedBy", SAAS.SupportTicket, SAAS.User , for name, domain, range in props: p = SAAS name g.add p, RDF.type, OWL.ObjectProperty g.add p, RDFS.domain, domain g.add p, RDFS.range, range The at-most-one half of the paper list g.add SAAS.onPlan, RDF.type, OWL.FunctionalProperty g.add SAAS.belongsTo, RDF.type, OWL.FunctionalProperty Datatype properties: attributes g.add SAAS.mrr, RDF.type, OWL.DatatypeProperty g.add SAAS.mrr, RDFS.domain, SAAS.Subscription g.add SAAS.mrr, RDFS.range, XSD.decimal g.add SAAS.isActive, RDF.type, OWL.DatatypeProperty g.add SAAS.isActive, RDF.type, OWL.FunctionalProperty g.add SAAS.isActive, RDFS.domain, SAAS.Subscription g.add SAAS.isActive, RDFS.range, XSD.boolean print f"{len g } triples so far" rdfs:domain and rdfs:range are not checks. If you write Acme filedBy Sub 001, a reasoner does not reject the triple. It implies that Acme is a SupportTicket. The check you probably want is SHACL, which arrives in Part 4. Domain and range still tell a query engine what the property is for owl:FunctionalProperty, onPlan, and belongsTo are at most one half of the paper list. A reasoner treats two different plans on one subscription as a contradiction. SPARQL will not enforce that by itself. isActive is functional too, and that one matters later; it tells the reasoner a subscription cannot be both active and inactive, which the churn rule will depend on. Now instances. The plans, and one customer: The three plans. Free is a FreePlan. Pro and Enterprise are PaidPlans.g.add SAAS.Free, RDF.type, SAAS.FreePlan g.add SAAS.Pro, RDF.type, SAAS.PaidPlan g.add SAAS.Enterprise, RDF.type, SAAS.PaidPlan One account with a live subscriptiong.add SAAS.Acme, RDF.type, SAAS.Account g.add SAAS.Sub 001, RDF.type, SAAS.Subscription g.add SAAS.Acme, SAAS.hasSubscription, SAAS.Sub 001 g.add SAAS.Sub 001, SAAS.onPlan, SAAS.Enterprise g.add SAAS.Sub 001, SAAS.mrr, Literal 4200.00, datatype=XSD.decimal g.add SAAS.Sub 001, SAAS.isActive, Literal True And one that churned: subscription exists, but lapsedg.add SAAS.Initech, RDF.type, SAAS.Account g.add SAAS.Sub 002, RDF.type, SAAS.Subscription g.add SAAS.Initech, SAAS.hasSubscription, SAAS.Sub 002 g.add SAAS.Sub 002, SAAS.onPlan, SAAS.Pro g.add SAAS.Sub 002, SAAS.mrr, Literal 900.00, datatype=XSD.decimal g.add SAAS.Sub 002, SAAS.isActive, Literal False print f"{len g } triples so far" The paper said an account is churned if it has no active subscription. Until that sentence is an OWL axiom, it is still a comment. Paste this Turtle into the graph. Turtle is the human-readable RDF syntax. You will save the whole graph as Turtle at the end. g.parse data="""@prefix saas: