A px workspace is one git repo holding a shared context vault plus one or more ontologies. This page is the reference for the files that describe an ontology’s lineage.

Workspace anatomy

Every YAML/manifest carries a $schema reference to a file under .px/schemas/, so any editor’s language server gives you autocomplete and validation as you type. The schema is the single source of truth px validate enforces.

The manifests

prometheux.workspace.yaml

ontologies/<slug>/prometheux.yaml

apply writes the assigned id back into this file after creating an ontology — commit it, so re-apply targets the same ontology. If the id is lost, apply reconciles by name (adopts a single existing same-name ontology in scope rather than duplicating), so a unique ontology name makes recovery reliable.

Concept kinds

A concept is a body file (concepts/<predicate>.<ext>) plus, for most kinds, a <predicate>.meta.yaml envelope. The body extension carries the language you authored — don’t rename everything to .vadalog.

The .meta.yaml envelope

Bind a predicate in binds.input only when it comes from a datasource. A predicate produced by another concept is a derived edge — never bind it (see below).

logic

Native Vadalog. customers.vadalog:

sql / cypher

Store the source query you wrote; the server transpiles it to Vadalog on apply, and pull recovers the source (not the transpiled form). revenue.sql:
The .meta.yaml uses conceptType: sql (or cypher).

python

A Python script — a leaf node, never parsed as Vadalog. enrich.py plus a enrich.meta.yaml with conceptType: python.

llm

A prompt template with llmConfig frontmatter and the prompt as the body. summarize.llm.md:

context

A note selection — static (pin note paths) or dynamic (retrieve by query). relevant.context.yaml:

The derived graph

You never hand-write lineage edges. A concept’s Vadalog head/body predicates are the edges:
Because customer and country_risk are produced by other concepts, px plan reconstructs the edge customer → risk automatically. There is no binds.input entry for them — only datasource-backed predicates get bound. Changing a concept’s rules invalidates its results and cascades to everything downstream; plan renders that cascade before you apply.

Datasources

Datasource specs live in datasources/*.yaml. Secrets are always ${ENV_VAR} placeholders, resolved from the environment at apply and never written to files.
Databases (postgres / mariadb / clickhouse / teradata / snowflake / …). Author one table per file so the concept binds it unambiguously (a DB connect returns the whole group):
For S3, splitting the path (host: s3a://my-bucket, database: airports) makes the connect succeed but drops the sub-dir from the stored bind — the concept then fails at run time with PATH_NOT_FOUND. Always put the whole path in host.
A concept reads a datasource through an input bind in its .meta.yaml (binds.input, referencing the datasource name). A datasource already on the account is reused (matched by type/host/port/table), not re-connected — so repeated applies never pile up duplicate rows.

Ontology and apps

  • ontologySchema (ontology/schema.yaml) — an entity/edge graph in the save_ontology_schema shape. The platform ontology view is drawn from concept lineage, so an ontology with a schema graph but no concepts renders empty; px validate warns about this.
  • apps/*.app.yaml — an AppDefinition v2. App project.id references are retargeted automatically when an ontology is recreated on another account.

Guardrails

  • Never put secrets in files — reference them as ${ENV_VAR}.
  • Never hand-write lineage edges, and never bind a predicate that another concept produces.
  • One table per datasource file for DB connections.
  • v1 concepts refer only within their own ontology — the only cross-ontology sharing is scope: global context.
Next: Context as code or the Command reference.