From config to instances
The Object Config Graph defines what can exist — types, relationships, functions, constraints. The Object Instance Graph (OIG) records what actually happens. Every time a function is called, a record is created, or a relationship is modified, the OIG captures that mutation as a committed, attributed, hash-chained receipt.
Think of it this way: the OCG is the schema. The OIG is the ledger.
Anatomy of a commit
Every OIG commit is a self-contained record of what changed, who changed it, and how the graph state evolved. Here is the structure:
{
"commit": {
"id": // Unique commit UUID
"author_id": // Who made this change (human or agent)
"commit_parents": // Parent commit(s) — forms the DAG
"created_at": // UTC timestamp
"lane_id": // Stable lane (branch + projection)
"status": // local | synced | confirmed
},
"graph_hash_pre": // SHA of graph state before
"graph_hash_post": // SHA of graph state after
"projection_hash": // Which projection this commit belongs to
"changes": [ // Array of mutations
{
"type": "CREATE" | "UPDATE" | "DELETE",
"class_instance_changes": [...],
"class_instance_relationship_changes": [...]
}
]
}
Key properties of every commit:
| Field | Purpose |
|---|---|
author_id |
Attribution. UUID of the actor — human user or AI agent. Always present. |
graph_hash_pre/post |
Hash continuity. The pre-hash of commit N must match the post-hash of commit N-1. |
commit_parents |
DAG lineage. Linear history by default; branching requires explicit opt-in. |
projection_hash |
Scoping. Ties the commit to a specific OPG projection (actor view). |
lane_id |
Derived from branch + projection. Multiple projections per branch are supported. |
The hash chain: tamper-evident by design
Every commit carries a graph_hash_pre and a
graph_hash_post. The validation rule is simple
and absolute:
The pre-hash of each commit must match the post-hash of its parent. If the chain breaks, the commit is rejected. No exceptions.
This gives the OIG a tamper-evident property similar to a blockchain, but without consensus overhead. The chain is validated locally and enforced at the commit boundary. If an agent produces a commit that does not match the expected graph state, it is rejected before it reaches storage.
Commit A
hash_post: 3a8f
Commit B
hash_pre: 3a8f
Commit C
hash_pre: d4e7
Linear history is enforced by default. A commit with more than one parent is rejected unless explicitly allowed. This keeps the graph simple and auditable while still supporting branching when the domain requires it.
The change model
Each commit contains one or more changes, and each change contains one or more deltas. The hierarchy:
ObjectInstanceGraphCommit → ObjectInstanceGraphChange[] → Change (CREATE | UPDATE | DELETE) → ChangeDelta[] (SCALAR_SET)
A single function call can produce multiple changes — for example, constructing a parent entity and its children in one operation. But all changes within a commit are atomic: they either all apply or none do.
Changes are typed by kind: instance mutations
(class_instance_changes) and relationship mutations
(class_instance_relationship_changes). This separation
makes it possible to replay, audit, or project changes independently.
Provenance: every action is attributed
Every commit carries an author_id. This is not optional.
When a human calls a function through the API, their identity is
the author. When an AI agent calls the same function through the
same typed API, the agent's identity is the author.
{
"actor_id": "a1b2c3d4-...", // Who
"operation_label": "identity.signup", // What canonical operation
"call_target": "instance", // Where in the graph
"function_id": "e5f6a7b8-..." // Which function was invoked
}
This metadata is indexed separately from the commit payload, making it possible to query "what did actor X do" or "which operations touched entity Y" without deserializing every commit.
Same graph. Same commits. Human or agent — always attributed. There is no separate "agent log" or "user activity feed." The commit history is the single source of truth for what happened and who did it.
Lanes: commits scoped by projection
Commits do not exist in a flat list. They live in lanes. A lane is identified by the combination of a branch and a projection hash. This means:
- Multiple projections (actor views) can exist on the same branch
- Each projection tracks its own HEAD commit
- The lane HEAD stores the latest commit ID and post-hash for resumption
{
"commit_id": "b2ddfd2c-492e-5a80-...",
"graph_hash_post": "460d30b861a9e873...",
"object_instance_graph_id": "475efb0e-4516-...",
"v": 1
}
The lane HEAD is what allows the system to resume from any point. When a new function call arrives, the committer reads the HEAD, validates hash continuity, appends the new commit, and advances the HEAD. The process is deterministic and repeatable.
Validation: what gets enforced
The OIG commit validator enforces a strict set of rules before any commit is accepted:
- Hash continuity — pre-hash must match parent's post-hash
- Linear history — single parent by default; multi-parent requires opt-in
- Root metadata — every commit must reference the root object and class config
- UTC timestamps — all timestamps in UTC, no timezone ambiguity
- Non-empty changes — empty commits are rejected (except seed commits)
- Author present — every commit must have an
author_id
If any rule fails, the commit is rejected with a typed validation error. The graph state does not change. This means the ledger is always consistent — there is no "partial commit" state.
The full flow: function call to committed receipt
When a human or agent calls a function on the canonical graph, this is what happens:
Actor
Human / Agent
API
Typed call
Handler
Graph ops
Commit
Validated
Lane
HEAD advanced
- The actor calls a typed function through the canonical API
- The handler executes graph operations (create, update, delete)
- The commit builder collects all changes into a commit
- The validator checks hash continuity, linearity, and attribution
- The committer writes the commit to the lane and advances the HEAD
- The commit is now a permanent, attributed receipt
The same flow applies whether the actor is a human user clicking a button in the interface, an AI agent making a tool call, or a service handler executing a scheduled operation. The graph does not distinguish by origin — it distinguishes by identity.
Why this matters for AI
AI agents in Aware are not wrappers around the system. They are first-class actors on the canonical graph. When an agent calls a function, it produces the same kind of commit a human would. The provenance stream shows agent and human actions side by side, with the same level of detail and accountability.
This design solves a fundamental problem with AI systems: auditability. When something goes wrong, you can trace back through the commit chain and see exactly which actor made which change, when, and what the graph state was before and after. No black boxes. No hidden state.
Why this matters for services
The OIG commit chain is what makes the economy rails possible. Pricing, settlement, smart contracts — all of these operate over the same committed receipts. When a service processes a transaction, the commit records what happened with full provenance. When a settlement is disputed, the hash chain provides an immutable audit trail.
For service providers on the Aware network, this means trust is built into the substrate. You do not need to build your own audit system. The canonical graph already is one.
The OIG is not just a database log. It is a canonical ledger where every action — human, agent, or automated — becomes a hash-chained, attributed, validated receipt. That is the foundation of trust in the Aware ecosystem.