Skip to main content
Domain ontologies are the central design concept in create-context-graph. A single YAML file defines everything about a domain — its entities, relationships, agent behavior, and visualization — and the tool uses that definition to generate an entire application. This page explains how that mechanism works.

What a domain ontology defines

A domain ontology is a structured YAML file that declares:

What exists

Entity types and their properties — the nodes in your knowledge graph

How things relate

Relationship types between entities — the edges in your knowledge graph

What the agent can do

Agent tools with Cypher queries and typed parameters

How the agent behaves

System prompt, demo scenarios, and guided chat examples

What data looks like

Document templates and decision trace scenarios for data generation

How it is visualized

Node colors, sizes, and the default Cypher query for the graph view
The ontology is not code. It is a declarative specification that gets fed into Jinja2 templates at generation time. The templates read the ontology and produce working Python, TypeScript, Cypher, and configuration files.

Two-layer inheritance

Every domain ontology is built on a shared base. The base ontology (_base.yaml) defines the POLE+O entity types that are common across all domains: The base also defines three common relationships: WORKS_FOR (Person → Organization), LOCATED_AT (Organization → Location), and PARTICIPATED_IN (Person → Event).

The inherits: _base mechanism

When a domain YAML declares inherits: _base, the ontology.py loader performs a merge:
  1. Base entity types are prepended to the domain’s entity list.
  2. Base relationships are prepended to the domain’s relationship list.
  3. If the domain defines an entity with the same label as a base entity (e.g., its own Person with extra properties), the domain version takes precedence and the base version is skipped.
This means every domain automatically gets Person, Organization, Location, Event, and Object nodes — plus the three base relationships — without redeclaring them.

YAML structure

A complete domain YAML contains these top-level keys:
Metadata about the domain: unique id, display name, description, tagline, and emoji.
The node types in your knowledge graph. Each entry defines a label, POLE+O category, visual appearance, and typed properties.
Typed, directed edges between entity labels.
Domain-specific tools the agent can call. Each tool includes a name, description, Cypher query, and typed parameters. These are iterated in the agent template to produce framework-specific tool definitions.
The system prompt injected verbatim into the agent configuration. Tells the LLM what domain it operates in, what tools are available, and how to behave.
Templates that drive the synthetic data generation pipeline. Each template specifies what kind of document to produce, how many, and which entities are required.
Reasoning scenarios for generating reasoning memory. Each trace has a task description and a sequence of thought/action steps, plus an outcome template.
Pre-built chat prompts that appear as clickable suggestions in the frontend, giving users a guided tour of the agent’s capabilities.
NVL graph visualization configuration: per-label node colors, node sizes (in pixels), and the default Cypher query used when the graph first loads.

Property types

Entity properties support these types, which map directly to Neo4j types and Python types in the generated code: Properties that set unique: true generate a Cypher uniqueness constraint. Properties that set required: true become mandatory fields in the generated Pydantic models.
YAML boolean values in enum lists must be quoted strings. Write enum: ["true", "false"], not enum: [true, false]. Unquoted YAML booleans will fail ontology validation.

How the ontology drives everything

The DomainOntology Pydantic model (defined in ontology.py) is loaded from the YAML and passed as context to every Jinja2 template. Each section of the ontology produces a different part of the generated application:

Entity types → Neo4j schema

Each entity_types entry with unique: true properties generates a Cypher uniqueness constraint. Every entity type also gets a name index for fast lookups:

Entity types → Pydantic models

Each entity label becomes a Python class in backend/app/models.py. enum properties generate Python Enum classes. Required properties become mandatory fields; optional ones default to None:

Agent tools → framework-specific code

The agent_tools list is iterated in agent.py.j2 to produce tool definitions in the chosen framework’s idiom. For PydanticAI, each tool becomes an @agent.tool decorated function. For LangGraph, each becomes a @tool function. The Cypher query and parameter definitions come directly from the YAML — no additional code is needed.

Visualization → NVL frontend

The visualization section (plus the color field on each entity type) populates the NVL component configuration in the Next.js frontend. Node colors, sizes, and the initial Cypher query for the graph view all come from the ontology.

Domain-agnostic templates, data-driven output

There are no per-domain template directories. The same Jinja2 templates produce a healthcare app, a financial services app, a wildlife conservation app, or any of the 22 built-in domains. The templates are parameterized entirely by the ontology context. This means:
  • Adding a new domain requires only a YAML file, not new templates.
  • Improvements to templates benefit all 22 domains simultaneously.
  • The template surface area stays small and maintainable regardless of how many domains exist.
The only template that varies by a non-ontology dimension is agent.py.j2, which has one version per supported agent framework. Even those framework-specific templates read the same ontology context — they just express tool definitions and agent setup in different framework idioms.

Extending with custom domains

Beyond the 22 built-in domains, you can create custom ontologies in two ways:
Follow the schema above, place the file in the domains/ directory (or ~/.create-context-graph/custom-domains/), and it becomes available as a --domain option:
Both paths produce the same result: a DomainOntology object that drives all the templates.

Next steps

Why context graphs?

How graph memory compares to flat stores and vector databases

Ontology YAML schema

Full reference for every field and option in the domain YAML format