# Domain Graph Protocol (DGP) - Full Agent Reference This file contains the current DGP core specification plus companion-spec index. - Core version: 0.9.0 - Core status: Production-Ready - Last updated: January 2026 - Reference implementation tests: 1048 passing ## Companion Spec Index ### Transport - NATS Transport (Draft): `https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-nats-transport-spec.md` ### Data Management - Consistency Model (Production-Ready): `https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-consistency-model-spec.md` - Conflict Resolution Across Sources (Draft): `https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-conflict-resolution-across-sources-spec.md` - Distributed Transactions / Saga Pattern (Draft): `https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-distributed-transactions-saga-pattern-spec.md` - Schema Evolution (Production-Ready): `https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-schema-evolution-spec.md` ### Security and Privacy - Data Privacy and Access Control (Draft): `https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-data-privacy-access-control-spec.md` - Query Safety and Resource Limits (Draft): `https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-query-safety-resource-limits-spec.md` ### Intelligence - Proactive Intelligence Layer (Draft Extension): `https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-proactive-intelligence-layer-spec.md` - CSN and Agent Context Management: `https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-csn-agent-context-management-spec.md` ### Operations - External Services (Production-Ready): `https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-external-services-spec.md` - Batch Queries and Error Taxonomy (Draft Extension): `https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-batch-queries-error-taxonomy-spec.md` - Query Planning Guide: `https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-query-planning-guide.md` --- # Domain Graph Protocol (DGP) ## Version 0.9.0 Specification **Authors:** Michael Beddows, Claude (Anthropic) **Status:** Production-Ready **Last Updated:** January 2026 **Tests:** 1048 passing --- ## Abstract The Domain Graph Protocol (DGP) is an agent-first interface specification for exposing business domains as unified, queryable graphs. Unlike traditional REST APIs that expose application boundaries, DGP exposes semantic domain models—the entities, relationships, and business logic that represent an organization's actual operational reality. DGP is designed for AI agents that need to understand and interact with business domains without learning multiple application-specific APIs. It prioritizes semantic clarity, relationship traversal, cost transparency, and data provenance. --- ## Table of Contents 1. [Core Principles](#core-principles) 2. [Terminology](#terminology) 3. [Domain Schema](#domain-schema) 4. [Query Language](#query-language) 5. [Response Format](#response-format) 6. [Mutations](#mutations) 7. [Subscriptions](#subscriptions) 8. [Cost Model](#cost-model) 9. [Extension Specifications](#extension-specifications) --- ## Core Principles 1. **Domain-First** — Expose business concepts (Customer, Order, Payment), not technical systems 2. **Graph-Native** — Every entity declares relationships; traversal is first-class 3. **No Schema References** — All schemas inline and self-contained 4. **Cost Transparency** — Every operation declares cost, latency, and freshness 5. **Provenance Built-In** — Responses include data sources, lineage, and cache status 6. **Composable Queries** — Agents compose from primitives: filter, join, aggregate, traverse 7. **Formal Semantics** — Type system, state machines, declarative business rules --- ## Terminology ### Core Terms | Term | Definition | |------|------------| | **Domain** | A coherent set of entities representing a business area | | **Entity** | A domain concept with attributes and relationships | | **Edge** | A typed relationship between entities with cardinality constraints | | **Attribute** | A typed property of an entity | | **Operation** | A mutation that changes entity state | | **Gateway** | The service implementing DGP, routing queries to sources | ### Graph Traversal Terminology DGP uses precise terminology for different types of traversal and nesting: | Term | Definition | Unit | Example | |------|------------|------|---------| | **Hop** | Single relationship traversal | Relationships | Customer → Order is 1 hop | | **Depth** | Query structural nesting level | Nesting levels | `include.orders.include.items` is depth 2 | | **Distance** | Number of hops between entities | Hops | Customer to LineItem via Order = distance 2 | #### Hop (Relationship Traversal) A **hop** counts each relationship traversed in a graph path: ``` Customer --[orders]--> Order --[items]--> LineItem 1 hop 2 hops (total) ``` **Used in:** - `relationship_hops`: Schema discovery traversal range - `max_hops`: Subscription filter scope - Distance calculations for related entity discovery #### Depth (Query Nesting) **Depth** counts structural nesting levels in queries: ```json { "query": { "entity": "Customer", // Depth 0 "include": { "orders": { // Depth 1 "include": { "items": { // Depth 2 "include": { "product": {} // Depth 3 } } } } } } } ``` **Used in:** - `max_depth`: Query safety limit for include nesting - `max_filter_depth`: Filter condition nesting limit - `max_evaluation_depth`: Policy recursion limit **Important:** Depth and hops are often equal but not always: ```json { "include": { "orders": {}, // 1 hop, depth 1 "support_tickets": {} // 1 hop, depth 1 (parallel, not nested) } } ``` This query has max depth 1 but traverses 2 relationships (2 total hops from Customer). #### Distance (Graph Metric) **Distance** is the shortest path length between two entities: ``` Customer → Order → LineItem → Product Distance(Customer, Product) = 3 hops ``` **Used in:** - Related entity scoring in schema discovery - Path optimization in query planning - Reachability analysis ### Depth vs Hops Quick Reference | Metric | Counts | Limited By | Use Case | |--------|--------|------------|----------| | Depth | Nesting levels | `max_depth` | Query complexity control | | Hops | Relationships traversed | `max_hops` | Relationship scope | | Distance | Shortest path length | - | Graph analytics | **Configuration Examples:** ``` # Query safety (depth-based) @max_depth 4 # Max include nesting levels # Schema discovery (hop-based) relationship_hops: 2 # Expand 2 relationships from seed entities # Subscription filters (hop-based) max_hops: 1 # Only direct relationships ``` --- ## Domain Schema ### Schema Structure ```json { "dgp_version": "0.9.0", "domain": { "name": "commerce", "version": "1.0.0" }, "entities": {}, "operations": {}, "cost_model": {} } ``` ### Entity Definition ```json { "Customer": { "description": "A person or organization that purchases products", "attributes": { "id": {"type": "uuid", "immutable": true, "indexed": true}, "email": {"type": "email", "required": true, "unique": true}, "name": {"type": "string", "required": true}, "lifetime_value": {"type": "decimal", "computed": true} }, "edges": { "orders": {"target": "Order", "cardinality": "many", "inverse": "customer"} } } } ``` ### Type System **Primitive Types:** `string`, `text`, `integer`, `decimal`, `float`, `boolean`, `uuid`, `timestamp`, `date`, `email`, `url`, `json` **Modifiers:** `required`, `unique`, `immutable`, `computed`, `indexed` **Composite:** `enum`, `array`, `object` > **See Also:** [Compressed Schema Notation (CSN)](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-csn-agent-context-management-spec.md) for 75-90% token reduction --- ### Relationship Cardinality Edges define typed relationships between entities with cardinality constraints. #### Cardinality Values | Cardinality | JSON Schema | CSN Syntax | Semantics | |-------------|-------------|------------|-----------| | `one` | `"cardinality": "one"` | `->1` | Exactly one target (required) | | `optional` | `"cardinality": "optional"` | `->?` | Zero or one target | | `many` | `"cardinality": "many"` | `->*` | Zero or more targets | #### Inverse Relationships Relationships may declare an inverse edge on the target entity: ```json { "Customer": { "edges": { "orders": { "target": "Order", "cardinality": "many", "inverse": "customer" } } }, "Order": { "edges": { "customer": { "target": "Customer", "cardinality": "one", "inverse": "orders" } } } } ``` **Inverse Validation Rules:** - If edge A declares `inverse: "B"`, edge B MUST declare `inverse: "A"` - Inverse cardinalities must be compatible (see Cardinality Compatibility Matrix) - Missing inverse declarations generate `INVERSE_DECLARATION_MISMATCH` during schema validation #### Cardinality Compatibility Matrix When edge A has cardinality X and declares inverse B with cardinality Y: | A's Cardinality | B's Cardinality | Valid | Relationship Type | |-----------------|-----------------|-------|-------------------| | `one` | `one` | Yes | 1:1 (bidirectional required) | | `one` | `optional` | Yes | 1:0..1 | | `one` | `many` | Yes | 1:N (A is "belongs to") | | `optional` | `optional` | Yes | 0..1:0..1 | | `optional` | `many` | Yes | 0..1:N | | `many` | `many` | Yes | M:N | --- ### Cardinality Constraint Enforcement Gateways MUST enforce cardinality constraints during mutations. #### Enforcement Timing | Mutation Type | Enforcement Point | Behavior | |---------------|-------------------|----------| | `create` | Before commit | Validate required relationships exist | | `update` | Before commit | Validate cardinality after changes | | `delete` | Before commit | Check dependent relationships | | `link` | Before commit | Prevent exceeding cardinality limits | | `unlink` | Before commit | Prevent violating required relationships | #### Enforcement Rules by Cardinality **`one` (Required Single)** ```json { "Order": { "edges": { "customer": {"target": "Customer", "cardinality": "one"} } } } ``` - **On create**: MUST provide exactly one customer reference - **On update**: Cannot nullify; can only replace with another valid reference - **On delete of Customer**: MUST reject if any Orders reference this Customer (unless `on_delete` specified) - **Violation error**: `CARDINALITY_VIOLATION` with `expected: "one"`, `actual: 0` or `actual: null` **`optional` (Optional Single)** ```json { "Order": { "edges": { "assigned_agent": {"target": "Agent", "cardinality": "optional"} } } } ``` - **On create**: May omit or provide exactly one reference - **On update**: Can set to null or replace with valid reference - **On link**: Fails if already linked (would create duplicate) - **Violation error**: `CARDINALITY_VIOLATION` with `expected: "optional"`, `actual: 2` **`many` (Multiple)** ```json { "Customer": { "edges": { "orders": {"target": "Order", "cardinality": "many"} } } } ``` - **On create**: May provide zero or more references - **On update**: Can add or remove without limit - **No upper bound enforcement** (use `@maxItems` annotation for limits) #### Extended Cardinality Constraints For fine-grained control, use cardinality bounds: ```json { "Project": { "edges": { "team_members": { "target": "User", "cardinality": "many", "min_items": 1, "max_items": 50 } } } } ``` **CSN Syntax:** ``` Project ->* team_members : User @minItems(1) @maxItems(50) ``` | Constraint | JSON | CSN | Enforcement | |------------|------|-----|-------------| | Minimum | `"min_items": N` | `@minItems(N)` | Reject if count < N | | Maximum | `"max_items": N` | `@maxItems(N)` | Reject if count > N | | Exact | `"min_items": N, "max_items": N` | `@exactItems(N)` | Reject if count ≠ N | #### Cascade Behaviors Define what happens when referenced entities are deleted: ```json { "Order": { "edges": { "customer": { "target": "Customer", "cardinality": "one", "on_delete": "restrict" }, "line_items": { "target": "LineItem", "cardinality": "many", "on_delete": "cascade" } } } } ``` | `on_delete` | Behavior | Use Case | |-------------|----------|----------| | `restrict` | Reject delete if references exist | Prevent orphans (default) | | `cascade` | Delete dependent entities | Parent-child relationships | | `set_null` | Nullify references (requires `optional`) | Optional associations | | `no_action` | Defer check to transaction end | Complex multi-step mutations | **CSN Syntax:** ``` Order ->1 customer : Customer @onDelete(restrict) ->* line_items : LineItem @onDelete(cascade) ``` #### Validation Error Details Cardinality violations return structured errors: ```json { "error": { "code": "CARDINALITY_VIOLATION", "category": "client_error", "message": "Relationship 'customer' requires exactly one target", "details": { "entity": "Order", "edge": "customer", "cardinality": "one", "constraint": { "min": 1, "max": 1 }, "actual": { "count": 0 }, "operation": "create" }, "help": { "suggestion": "Provide a valid Customer reference in the 'customer' field" } } } ``` #### Deferred Constraint Checking For complex mutations requiring temporary constraint violations: ```json { "mutation": { "operation": "batch_reassign", "options": { "constraint_check": "deferred" }, "steps": [ {"unlink": {"entity": "Order", "id": "ord_1", "edge": "customer"}}, {"link": {"entity": "Order", "id": "ord_1", "edge": "customer", "target": "cust_new"}} ] } } ``` **Constraint Check Modes:** | Mode | Behavior | |------|----------| | `immediate` | Check after each operation (default) | | `deferred` | Check at transaction commit | When using `deferred`, violations are detected at commit time and the entire transaction rolls back. --- ### Inverse Relationship Validation Inverse relationships enable bidirectional traversal and must maintain consistency. #### Schema-Time Validation When a schema is loaded, the gateway MUST validate all inverse declarations: **Rule 1: Symmetric Declaration** ```json { "Customer": { "edges": { "orders": {"target": "Order", "cardinality": "many", "inverse": "customer"} } }, "Order": { "edges": { "customer": {"target": "Customer", "cardinality": "one", "inverse": "orders"} } } } ``` If `Customer.orders` declares `inverse: "customer"`, then `Order.customer` MUST: - Exist on the Order entity - Have `target: "Customer"` - Declare `inverse: "orders"` **Rule 2: Target Consistency** The inverse edge's target MUST match the source entity: - `Customer.orders` targets `Order` → `Order.customer` MUST target `Customer` **Rule 3: Cardinality Compatibility** Inverse cardinalities must form valid relationship patterns: | Source Edge | Inverse Edge | Valid Pattern | |-------------|--------------|---------------| | `one` | `many` | Parent-child (Order → Customer) | | `many` | `one` | Child-parent (Customer → Orders) | | `one` | `one` | 1:1 relationship | | `optional` | `many` | Optional belongs-to | | `many` | `many` | M:N junction | | `optional` | `optional` | Optional 1:1 | #### Schema Validation Errors ```json { "error": { "code": "INVERSE_DECLARATION_MISMATCH", "category": "client_error", "message": "Inverse relationship declarations are inconsistent", "details": { "source": { "entity": "Customer", "edge": "orders", "target": "Order", "inverse": "customer" }, "expected_inverse": { "entity": "Order", "edge": "customer", "target": "Customer", "inverse": "orders" }, "actual_inverse": { "entity": "Order", "edge": "customer", "target": "Customer", "inverse": null }, "violation": "missing_inverse_declaration" } } } ``` **Violation Types:** | Violation | Description | |-----------|-------------| | `missing_inverse_declaration` | Target edge doesn't declare inverse | | `inverse_target_mismatch` | Inverse doesn't point back to source | | `inverse_edge_not_found` | Declared inverse edge doesn't exist | | `cardinality_incompatible` | Cardinalities don't form valid pattern | #### Runtime Inverse Consistency When mutations modify relationships, gateways MUST maintain inverse consistency: **Link Operation:** ```json { "mutation": { "operation": "link", "entity": "Order", "id": "ord_123", "edge": "customer", "target": "cust_456" } } ``` Gateway MUST atomically: 1. Add `cust_456` to `Order.ord_123.customer` 2. Add `ord_123` to `Customer.cust_456.orders` (via inverse) **Unlink Operation:** ```json { "mutation": { "operation": "unlink", "entity": "Customer", "id": "cust_456", "edge": "orders", "target": "ord_123" } } ``` Gateway MUST atomically: 1. Remove `ord_123` from `Customer.cust_456.orders` 2. Remove/nullify `cust_456` from `Order.ord_123.customer` (via inverse) #### Inverse Consistency Modes For distributed systems where atomic inverse updates aren't possible: ```json { "domain": { "name": "commerce", "inverse_consistency": "eventual" } } ``` | Mode | Behavior | Use Case | |------|----------|----------| | `strict` | Atomic inverse updates (default) | Single-source systems | | `eventual` | Async inverse propagation | Distributed sources | | `manual` | No automatic inverse updates | Legacy integration | **Eventual Consistency Behavior:** When `inverse_consistency: "eventual"`: 1. Primary edge update commits immediately 2. Inverse update queued for async processing 3. Queries may see temporary inconsistency 4. Gateway provides `inverse_sync_status` in metadata ```json { "metadata": { "inverse_sync_status": { "pending": [ { "source": "Order.ord_123.customer", "inverse": "Customer.cust_456.orders", "queued_at": "2026-01-28T10:30:00Z" } ] } } } ``` #### CSN Inverse Syntax ``` Customer @cost(2) ->* orders : Order @inverse(customer) Order @cost(1) ->1 customer : Customer @inverse(orders) ``` **Validation during CSN parsing:** - Parser tracks all `@inverse()` declarations - After full parse, validates symmetric declarations - Reports all violations before schema activation #### Query Traversal via Inverse Inverse relationships enable queries from either direction: ```json { "query": { "entity": "Customer", "where": {"id": {"eq": "cust_123"}}, "include": { "orders": {"limit": 10} } } } ``` Is equivalent to (via inverse): ```json { "query": { "entity": "Order", "where": {"customer.id": {"eq": "cust_123"}}, "limit": 10 } } ``` The gateway MAY optimize query execution by choosing the more efficient traversal direction based on: - Index availability - Estimated result set size - Data source capabilities --- ## Query Language ### Basic Query ```json { "query": { "entity": "Customer", "where": {"lifetime_value": {"gte": 1000}}, "include": { "orders": {"limit": 5, "order_by": {"created_at": "desc"}} }, "limit": 10 } } ``` ### Filter Operators `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`, `nin`, `contains`, `starts_with`, `ends_with`, `exists`, `and`, `or`, `not` ### Aggregations ```json { "aggregate": { "total_orders": {"count": "orders"}, "total_revenue": {"sum": "orders.total"} } } ``` > **See Also:** [Query Safety & Resource Limits](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-query-safety-resource-limits-spec.md) --- ## Response Format ```json { "data": [], "metadata": { "query_id": "q_abc123", "execution": {"duration_ms": 145, "sources_queried": ["postgres", "stripe"]}, "cost": {"total_tokens": 67}, "freshness": {"staleness_ms": 2300}, "provenance": {"sources": [], "transformations": []} }, "pagination": {"total": 1234, "has_more": true} } ``` > **See Also:** [Consistency Model](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-consistency-model-spec.md) for `consistency_token` and levels --- ## Mutations ### Mutation Request ```json { "mutation": { "operation": "confirm_order", "entity": "Order", "id": "order_123", "input": {"payment_method_id": "pm_xyz"}, "options": {"idempotency_key": "idem_abc123"} } } ``` ### Mutation Response ```json { "success": true, "data": {}, "metadata": { "mutation_id": "m_xyz", "side_effects_executed": [ {"action": "charge_payment", "status": "success"} ] } } ``` > **See Also:** [Distributed Transactions (Saga Pattern)](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-distributed-transactions-saga-pattern-spec.md) --- ## Subscriptions Real-time entity change notifications via NATS pub/sub. ### Subscribe ```json { "subscription": { "entity": "Order", "events": ["created", "updated", "state_changed"], "where": {"customer.id": {"eq": "cust_123"}} } } ``` ### Event Envelope ```json { "event_id": "evt_abc123", "entity": "Order", "entity_id": "ord_123", "event_type": "updated", "actor": {"type": "agent", "id": "agent_xyz"}, "changes": {"status": {"from": "pending", "to": "confirmed"}}, "data": {} } ``` > **See Also:** [NATS Transport Specification](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-nats-transport-spec.md) for full implementation details --- ## Cost Model ```json { "cost_model": { "base_query": 10, "per_entity": 1, "per_relationship": 5, "per_filter_condition": 0.5, "per_aggregate": 3, "cache_hit_discount": 0.5 } } ``` --- ## Extension Specifications DGP capabilities are extended through these specifications: ### Transport | Spec | Description | |------|-------------| | [NATS Transport](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-nats-transport-spec.md) | Real-time subscriptions, request/reply over NATS | ### Data Management | Spec | Description | |------|-------------| | [Consistency Model](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-consistency-model-spec.md) | Strong, eventual, bounded_staleness levels | | [Conflict Resolution](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-conflict-resolution-across-sources-spec.md) | LWW, vector clocks, merge functions | | [Distributed Transactions](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-distributed-transactions-saga-pattern-spec.md) | Saga pattern for multi-source mutations | | [Schema Evolution](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-schema-evolution-spec.md) | @deprecated, version negotiation, migrations | ### Security & Privacy | Spec | Description | |------|-------------| | [Data Privacy & Access Control](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-data-privacy-access-control-spec.md) | RBAC, ABAC, PII classification, masking | | [Query Safety](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-query-safety-resource-limits-spec.md) | Rate limiting, cost budgets, depth limits | ### Intelligence | Spec | Description | |------|-------------| | [Proactive Intelligence Layer](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-proactive-intelligence-layer-spec.md) | Schema discovery, statistics, health monitoring | | [CSN](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-csn-agent-context-management-spec.md) | Compressed Schema Notation for agents | ### Operations | Spec | Description | |------|-------------| | [External Services](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-external-services-spec.md) | Service registry, health, auth, failure handling | | [Batch Queries & Errors](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-batch-queries-error-taxonomy-spec.md) | Batch operations, error taxonomy | | [Query Planning](https://github.com/pyramidal-io/DGP.dev/blob/main/docs/dgp-query-planning-guide.md) | Optimization strategies | --- ## Implementation ### Python Reference ```bash pip install dgp-python[all] ``` ```python from dgp import DGPSchema, QueryBuilder from dgp.adapters.nats import AsyncNATSAdapter # Build query query = QueryBuilder("Customer").where("ltv", gte=1000).build() # Execute result = await adapter.execute(query) ``` ### Gateway Endpoints | Endpoint | Method | Purpose | |----------|--------|---------| | `/schema` | GET | Domain schema | | `/query` | POST | Execute query | | `/mutation` | POST | Execute mutation | | `/health` | GET | Gateway health | --- ## Version History | Version | Date | Highlights | |---------|------|------------| | 0.9.0 | Jan 2026 | NATS transport, real-time subscriptions | | 0.8.0 | Dec 2025 | Consistency model | | 0.7.0 | Dec 2025 | Schema evolution | | 0.6.0 | Dec 2025 | Conflict resolution | | 0.5.0 | Dec 2025 | Distributed transactions | | 0.4.0 | Nov 2025 | Data privacy, access control | | 0.3.0 | Nov 2025 | Query safety, rate limiting | | 0.2.0 | Nov 2025 | Multi-source federation | | 0.1.0 | Nov 2025 | Initial draft | --- ## Resources - **Website:** https://dgp.dev - **GitHub:** https://github.com/pyramidal-io/DGP.dev - **For AI Agents:** https://dgp.dev/llms.txt --- ## License MIT License. Copyright (c) 2025-2026 Michael Beddows. --- **End of Specification v0.9.0**