Manta Developers
GitHub
Menu

Knowledge graph and datastores

Where your data lives in Manta and how it gets there.

Everything in Manta lives in a knowledge graph: your entities, the relationships between them, the facts rules derive from them, and the plans an agent proposes. Each tenant’s graph is a datastore.

Datastores

A datastore is one tenant’s graph, addressed by its id. Every part of the SDK takes that id:

  • React: the datastoreId prop on EmbeddedChatProviders
  • CLIs: the --datastore flag on manta-codegen, manta-upload and manta

Requests from the browser carry the session cookie of your Manta deployment (mantaBaseUrl, which defaults to https://app.hiremanta.com), so a user only reaches the datastores they have been granted.

Getting data in

There are two ways to fill a datastore.

Connect a source. Manta integrates with the platforms your data already lives in, such as Meta, Google Ads, Google Analytics and LinkedIn. Once a source is connected, its data is synced into the datastore.

Upload files. @manta-eu/upload sends files from a script, a scheduled job or another system’s export:

pnpm manta-upload people.csv orders.parquet --datastore your-datastore
  • CSV, Parquet, Turtle and N-Triples files are ingested into the knowledge graph. Any other type is stored but not ingested. Pass --bundle to store a file without ingesting it.
  • Ingestion runs in batches a few minutes after the upload.
  • Each upload records how its ingestion went, so you can query whether a file was ingested, unparsable, too_large or gone.
  • A CSV row becomes an entity and each column a property, with no mapping to write. To link entities to each other, or to update them by uploading again, send Turtle or N-Triples with your own IRIs. Upload explains both.

An upload never creates a datastore: get one from Manta first. A custom app can also write triples directly with SPARQL updates, once an admin allows it.

Your app’s vocabulary

Your app’s own classes and properties belong in a Turtle file in your repo. The manta CLI from @manta-eu/cli makes the datastore hold exactly what that file declares:

pnpm manta ontology push manta/ontology.ttl --datastore your-datastore --name your-app \
  --namespace https://your-app.example/vocab#
  • Each app’s vocabulary lives in its own named graph, an owl:Ontology like the realm’s ontology graph, so a push never changes the realm’s ontology or another app’s vocabulary. Ontology coverage does not count it as data.
  • A second push of the same file changes nothing, so it can run in CI after every merge. --dry-run shows what would change. A file with blank nodes, such as a list, is rewritten on every push, with the same result.
  • Declare classes as rdfs:Class and properties as rdf:Property, with an rdfs:label and rdfs:comment, as the realm ontology does.
  • --namespace names your app’s namespace, and every term the file declares must be under it. A namespace that overlaps one Manta already uses (the realm’s own, an integration’s, or a W3C vocabulary) or another app already claims is refused, and so are terms the realm ontology or another app’s vocabulary already describes.
  • A custom app pushes its own vocabulary with its machine token, when it may write data. An operator’s login or service account works too. A token the app issued to one of its users only reads. Only the app that pushed a vocabulary, or an operator, may change or delete it.

Shapes for your classes

SHACL shapes say which properties a class carries, their datatypes and how many values each takes. manta-codegen turns them into typed LDKit schemas. Keep them in a second Turtle file:

pnpm manta shapes push manta/shapes.ttl --datastore your-datastore --name your-app
  • Your shapes join the realm’s in the datastore’s shapes graph, tagged with your --name. A push replaces only your shapes, and a realm deploy keeps them. Manta also stores a copy, so a rebuilt datastore gets them back. Only the shapes are stored, so push your vocabulary again on a rebuilt datastore before a custom app changes its shapes.
  • A shape may target your own classes, or one your data brings in through sh:targetClass. A shape you push for a class Manta inferred from an upload takes over from the inferred one. A class the realm’s own shapes or another app’s shapes already cover is refused.
  • Delete your shapes before your vocabulary: a vocabulary whose shapes are still in the datastore cannot be deleted.
  • Name your shapes in your app’s own namespace. Names in a namespace Manta uses, or that the realm or another app already uses, are refused, and so are Manta’s own predicates.
  • A custom app pushes or deletes only the shapes of a vocabulary it pushed itself.
  • Give your namespace a prefix of its own (@prefix todo: <…>) in your vocabulary. The vocabulary push keeps it, so manta-codegen writes your schemas to todo.ts.

Rules for your data

Datalog rules derive new facts from the ones in the graph, and the datastore keeps the derived facts up to date as data changes. Keep your app’s rules in a .dlog file, each named by a # s: line in your own namespace, and push them:

pnpm manta rules push manta/rules.dlog --datastore your-datastore --name your-app
  • The push commits the file as your app’s whole rule set in one transaction: it adds, replaces and removes rules so the datastore runs exactly what the file holds. --dry-run reports the changes without committing them.
  • Your rules belong to your app, so a realm deploy keeps them, and another owner’s rules are never taken over.
  • Use only the prefixes the realm’s rules declare, and spell your own IRIs out in full: a realm deploy recommits your rules under the realm’s prefixes.
  • A rule that derives a protected predicate, declares or rebinds a prefix the realm’s rules do not, or is not valid Datalog is refused, and nothing is committed.

Reading the graph

The graph is queried with SPARQL. In a React app you rarely write SPARQL yourself: the SDK reads and writes entities through schemas and LDKit, and the agent queries the graph for you.

Pages in this chapter