Skip to main content

Versioned property-graph schema for agentic decision structures (dg/v1) — spec, validator, and generators

Project description

dg — decision-graph spec

DRAFT — pre-1.0. Schema is settled in shape; the JSON spec format is a first-iteration draft and will likely refine before stable release.

dg is a versioned property-graph schema for representing decision structures — the choices, actions, and communications an AI agent (or human, or hybrid system) makes during a workflow run. It's designed to be the canonical target for mapping any decision-making data, including OpenTelemetry agent traces, into

  1. Contntext graph (Neo4j or any property-graph database)
  2. Analytics-ready tabular data (Arrow / Parquet) for ML training pipelines, RL, and agentic research.

The spec exists as a machine-readable JSON document (spec.json) plus a human-readable design rationale (design.md). The JSON spec is intended to drive auto-generators in consumer libraries — Arrow schema generation, Cypher constraint / index / upsert templates, validation tooling, etc.

What's in this repo

File Purpose
spec.json Canonical machine-readable schema. Property types, node definitions (with labels, upsert keys, indexes, properties, inheritance), relationship definitions (with from/to, cardinality, edge properties).
design.md Full design rationale — locked decisions and the why behind them, layering, identity rules, namespacing contract, provenance contract, mapping from OpenTelemetry agent-trace formats, considered-and-rejected alternatives, open questions.
arrows.json Supplementary Arrows.app-importable JSON for visual editing. Renders the schema as a property-graph diagram. Open at arrows.app and paste contents.

Why three artifacts

  • spec.json is what tooling consumes. Auto-generators read it; validators check instances against it.
  • design.md is what humans read to understand why the schema looks the way it does. New consumers should start here.
  • arrows.json is what humans use to see the schema as a diagram and to propose edits visually. Re-export from Arrows back into this file when changes are accepted.

The three should stay in sync — if you change one, update the others.

Layers at a glance

                     ┌────────────────────────┐
                     │   Evaluation layer     │  scores, judgments — produced
                     │   (:Evaluation)        │  separately from the workflow
                     └────────────┬───────────┘
                                  │ EVALUATES
                                  ▼
┌─────────────────┐   FOR_TASK   ┌───────────────────────┐
│ Reference layer │◄─────────────│  Execution layer       │
│ (resolve down)  │              │  (UUIDs / OTel ids)    │
│ Task, Actor,    │              │  WorkflowExecution,    │
│ Tool, Resource  │              │  StepExecution         │
│  (incl. :Model) │              │  (:ToolCall :Reasoning │
│ Session         │              │   :Message)            │
└─────────────────┘              └────────────────────────┘
  • Reference layer — natural keys, MERGE on upsert. Same gpt-4o-mini everywhere; same Tool {service_name, name, version} across all workflows. Resolves down across runs.
  • Execution layer — IDs derived from OTel trace_id / span_id when sourced from OTel (so re-ingestion is idempotent); UUIDs otherwise. Per-run state with timestamps, status, errors, provenance. Edges to the reference layer carry per-call data (token counts, model identity, tool args).
  • Evaluation layer — independent provenance, EVALUATES back into the execution layer. Produced by separate eval pipelines (LLM judges, human review batches, automated tests).

See design.md for the full reference.

Consuming the spec

The intended pattern is for downstream libraries to:

  1. Read spec.json (pin to a tagged version)
  2. Generate Arrow schemas from the node + relationship definitions
  3. Generate Cypher CREATE CONSTRAINT / CREATE INDEX / parameterized MERGE upsert templates per node label and edge type
  4. Validate instance documents against the spec

The reference implementation is otela, which will produce dg/v1 instance data from OTel agent traces.

Installing

pip install --pre decision-graph
# or with uv:
uv add --prerelease=allow decision-graph

The --pre flag is needed while dg/v1 is in alpha (1a0, 1a1, ...). Once v1 ships stable, drop it.

The package ships with the bundled dg/v1 spec accessible as decision_graph.SPEC_PATH (a pathlib.Path) and decision_graph.load_spec() (a parsed dict). It has no runtime dependencies.

Validating an instance

A dg-instance JSON document is a single file with nodes and relationships arrays:

{
  "spec": "dg",
  "spec_version": "v1",
  "nodes": [
    {"id": "n1", "labels": ["Tool"], "properties": {"service_name": "...", "name": "...", "version": "..."}}
  ],
  "relationships": [
    {"type": "CALLS_TOOL", "from_id": "tool-call-1", "to_id": "n1", "properties": {}}
  ]
}

The instance-level node id is an opaque handle used for relationship endpoint resolution within the file. The spec's properties.id (where present) is a separate concept — the natural identity used for upsert into a graph DB.

Validate against the bundled spec:

python -m decision_graph.validator path/to/instance.json

Or programmatically:

import decision_graph
from decision_graph.validator import SpecModel, validate

spec = SpecModel(decision_graph.load_spec())
errors = validate(instance_dict, spec)
for err in errors:
    print(err)

The validator checks structural shape, property types and constraints (enums, minLength, minimum, format=json, nullable), edge endpoint type matching (via extends chains so an :Actor:Agent is accepted where :Actor is required), dangling endpoint detection, and upsert-key uniqueness grouped by upsert root (an Agent and a Human with the same (service_name, name, version) will collide under the abstract Actor constraint, matching the Cypher-generation intent).

To validate against a spec on disk (e.g., a different version):

python -m decision_graph.validator path/to/instance.json --spec path/to/spec.json

Versions

Version Status Tag Notes
v1 DRAFT (alpha) v1a0 Initial pre-release. Three layers (reference / execution / evaluation), Actor-centric execution, OTel-derived idempotency.

The package's major version tracks the schema version: alpha releases of dg/v1 are tagged v1a0, v1a1, ...; the stable dg/v1 release is v1; the next schema generation goes to v2a0, then v2. The main branch reflects the in-progress next release. For a stable consumable spec, install a tagged release from PyPI or pin to a tag.

Status and stability

dg/v1 is DRAFT in alpha. The schema shape is settled (locked decisions in design.md); what's still in flux is the JSON spec format itself — spec.json is a first iteration of a JSON-Schema-flavored DDL with custom extensions for graph-DDL concerns (extends, upsert_key, indexes, $arrow). The format (meta.format_version: "0.1") is expected to refine before v1 is tagged stable.

Once a version is tagged stable, its spec.json is immutable at that tag. Iteration during alpha happens via pre-release tags (v1a0, v1a1, ...); subsequent schema generations get a new version (v2a0, v2, ...).

Contributing

This is an early project. The way to contribute right now is to open an issue describing a real-world OTel trace shape, ML use case, or graph-query pattern that the current schema doesn't support cleanly. Concrete examples beat abstract proposals.

When the schema does change, the version's design.md "Changes from previous version" section captures the diff with rationale; the GitHub Release notes summarize.

License

Apache-2.0.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

decision_graph-1a0.tar.gz (35.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

decision_graph-1a0-py3-none-any.whl (20.1 kB view details)

Uploaded Python 3

File details

Details for the file decision_graph-1a0.tar.gz.

File metadata

  • Download URL: decision_graph-1a0.tar.gz
  • Upload date:
  • Size: 35.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for decision_graph-1a0.tar.gz
Algorithm Hash digest
SHA256 39a5463f074cb90293716a7bd5eebf4271a2983523c3b59adc3d65795aa577fe
MD5 6fc4420fff85565c7fe0d83723273efc
BLAKE2b-256 b8004e5fefb5bec7533d699f5ab75ba077fbe7fafebdfebd721e56856782568d

See more details on using hashes here.

Provenance

The following attestation bundles were made for decision_graph-1a0.tar.gz:

Publisher: release.yml on decision-graph/decision-graph

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file decision_graph-1a0-py3-none-any.whl.

File metadata

  • Download URL: decision_graph-1a0-py3-none-any.whl
  • Upload date:
  • Size: 20.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for decision_graph-1a0-py3-none-any.whl
Algorithm Hash digest
SHA256 e4279b6593ad4ab2ca8e29cfb52b674485589f28625cb776695bd43764b298e6
MD5 43395f04eb4dd899492ce25a03f34ef0
BLAKE2b-256 86671187e59607d0097f8811b2818b859aeb6f1ae41afc7365920cfc62d58428

See more details on using hashes here.

Provenance

The following attestation bundles were made for decision_graph-1a0-py3-none-any.whl:

Publisher: release.yml on decision-graph/decision-graph

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page