MindGraphDocs

Operational Ontology (Layer 7)

Layer 7 is a semantic contract: you define the domain objects and relations your work centers on — Clients, Orders, Contracts, Patients, Cases — once, then bind them to the systems you already run. Connect a SQL database and your rows become typed objects; ingest documents and the unstructured context fuses onto the same objects. Your agents query both through one typed contract, with a source on every fact.

Note:MindGraph stores ontology objects and their cognitive context in MnesticDB. A connected Postgres database is an optional read-only source for mapped fields, not the engine that powers MindGraph.
Note:Layers 1–6 (Reality, Epistemic, Intent, Action, Memory, Agent) describe how an agent reasons. Layer 7 describes your world. They compose: a mapped Customer: Acme Corp (synced from your database) links to cognitive nodes like Claim: “Acme is frustrated with onboarding”, RiskAssessment: churn risk, Decision: flag for renewal review — extracted from a call transcript and attached to the very same object.

Two ways to populate an object type

Each object type declares an optional backing — where its instances come from:

  • Mapped — bound to an external SQL table (primary key + column→field map). Instances are kept in sync by a read-only projection. Use this when the fact already lives in a database.
  • Extracted — pulled from unstructured documents/transcripts by the per-chunk LLM extraction pass. Use this when no structured source exists (notes, emails, PDFs).
  • Authored — written directly via the API/agent.

The wedge is that one object type can be backed by a SQL mapping and unstructured extraction at once — fused by identity resolution onto a single node. The CRM row and what last week's meeting said about that customer end up on the same object. Don't recreate cognitive types (Claim, Evidence, Decision, Risk, Task, Goal, …) as object types — those are built-ins and Layer 7 composes with them.

Connect a SQL database

The primary path: bind a Postgres database and let MindGraph draft the ontology from its schema. Full walkthrough in Connect a database. In short, from Dashboard → Ontology → Connect a database:

  1. Connect a read-only Postgres role (encrypted at rest; we never write back).
  2. MindGraph introspects tables, primary keys, and foreign keys.
  3. Propose from your schema — an LLM drafts typed object types (with backing pre-filled, fields marked indexed vs live) and relations from your FKs.
  4. Review the mappings in the Mapped Data tab, confirm the primary key + title, and activate.
  5. Sync now — your rows become thin Layer::Ontology objects.
Note:Connection management (creating/credentials/sync) lives in the dashboard, not the SDKs — a read-only credential-custody surface stays in one audited place. The SDKs and MCP server consume the resulting objects through the read tools below.

Fusion: structured + unstructured on one object

When you ingest documents or conversations that mention a mapped object, the extraction entity resolver recognizes it and attaches the cognitive overlay (claims, risks, decisions) to the existing mapped node rather than forking a duplicate. A conversational assertion that disagrees with an indexed mapped field becomes a Contradicts relation, not a silent overwrite — the connected database remains authoritative for that mapped field, and the overlay records the belief over time.

Generated agent read tools

From the active schema, MindGraph generates read-only tool descriptors per object type — served at GET /v1/ontology/tools and rendered by the MCP server at session start:

  • search_<objs>(query) — find objects (mapped + extracted) by keyword or meaning
  • get_<obj>(uid) — fetch one object
  • summarize_<obj>(uid) — the object plus its cognitive context (claims, risks, decisions, evidence). The fusion payoff: the live row and what was said about it, in one call.
import { MindGraph } from "mindgraph";
const mg = new MindGraph({ baseUrl: "https://api.mindgraph.cloud", apiKey: "mg_..." });

// The read-tool manifest for the active schema (MCP renders these into tools).
const { tools } = await mg.listOntologyTools();

// Query the ontology directly, with cognitive context fused in.
const result = await mg.queryOntology({
  query: "Which customers are a churn risk?",
  include_cognitive_context: true,
});

Object type fields & backing

Each object type defines a list of fields. Allowed field types:

  • string, number, integer, boolean, date, datetime, object, json
  • enum — requires enum: ["a", "b"]
  • reference — requires reference_object_type (must exist in the same schema)
  • array — requires array_item_type (scalar item types only)

A mapped object type also carries a backing that binds it to a SQL source. Each field is marked indexed (projected into the node, embedded, searchable, reasoned-about) or live (declared but fetched from the source on demand at read time — never stored, so never stale):

{
  "kind": "sql",
  "sources": [{
    "connection_ref": "conn_…",
    "table": "customers",
    "key": "id",
    "field_map": {
      "name":   { "column": "full_name",     "mode": "indexed" },
      "tier":   { "column": "account_tier",   "mode": "indexed" },
      "balance":{ "column": "annual_value",   "mode": "live"    }
    }
  }],
  "primary_key": "id",
  "title_field": "name",
  "sync": { "mode": "incremental", "cursor_column": "updated_at" }
}

Relations can be mapped too: sql_fk (a foreign-key column) or sql_join_table (a M:M junction table) materialize into typed bridge edges. Object types also declare identity_fields — the subset whose values uniquely identify an instance, used to dedup and to fuse extracted mentions onto mapped objects.

Authoring from documents

If a type has no structured source, populate it by extraction. Propose a schema from a description (and optional sample docs), activate it, then ingest with the ontology layer enabled — uncertain extracted objects land under Extracted data in the Review queue. Semantic archetype classifications are reviewed separately under Semantic guidance.

After activating a new schema, use Extract existing sources in the dashboard to backfill ontology objects from documents that were ingested before the schema existed. Progress and failures remain visible rather than being reported as a successful empty run.

// Propose from a description (documents optional), then activate.
const { schema_id } = await mg.proposeOntologySchema({
  description: "Client-services agency: clients, projects, contracts, risks.",
  template_hint: "client_services",
});
await mg.activateOntologySchema(schema_id);

// Ingest with ontology extraction; mapped types are skipped (they sync instead).
await mg.ingestDocument({
  content: "Acme Corp signed a new contract on Mar 14 ...",
  layers: ["reality", "epistemic", "ontology"],
  ontology_schema_id: schema_id,
});

// Review + approve extracted proposals.
const { items } = await mg.listOntologyProposals({ status: "pending" });
for (const p of items) await mg.approveOntologyProposal(p.id);

Reserved type names

Object type names cannot collide with MindGraph built-in NodeType variants (case-insensitive). Person, Organization, Document, Claim, Decision, etc. are reserved — use workspace-specific names like Customer, Supplier, Patient. The cloud API rejects collisions with 409 reserved_type_name.

Provenance & review

Mapped objects carry a source_handle (connection, table, pk) and per-field origins (sql), and are read-projected — extraction never overwrites a SQL-owned field. Extracted objects carry a source_uids array and an ExtractedFrom edge to each source chunk, so queries return source excerpts. Review policy is per type: "never" auto-approves above a 0.50 floor, "low_confidence" auto-approves at or above the type's default_confidence, "always" queues every proposal.

Note:Layer 7 is opt-in and backward-compatible. Existing six-layer ingestion (no layers:["ontology"]) behaves byte-identically — no extra LLM calls, no extra DB writes. A type with no backing is purely extracted/authored, exactly as before.