Derived memories and source revisions
Available in 0.8.0. Use a derived memory for a summary, extracted claim or agent-produced conclusion that should remain usable only while its recorded sources remain current. QilbeeDB stores externally produced content; it does not invoke a model or infer that the sources logically support the conclusion.
Create a derived record#
Call POST /api/v1/memory/commands with both memory_read and memory_write for
the exact scope. Use the existing command envelope with operation.type: derive:
{
"contract_version": 1,
"idempotency_key": "derive-run-42",
"scope": {"project_id": "project", "mission_id": null, "agent_id": "agent", "visibility": "shared"},
"operation": {
"type": "derive",
"record": {
"episode_type": "Observation",
"event_time_millis": 1700000000000,
"content": {"primary": "The observed failure was caused by an expired credential."},
"tags": ["derived"]
},
"derivation": {
"sources": [{"record_id": "00000000-0000-4000-8000-000000000042", "revision": 2}],
"method": "incident-summary",
"method_revision": "prompt-v3",
"evidence_ref": "trace://incident/42"
}
}
}
Source IDs refer exclusively to the authenticated namespace: tenant, project, mission, agent and visibility, plus the subject for private memory. A source ID cannot grant access to another namespace. The caller cannot supply a source namespace, tenant or author.
derivation requires 1–16 unique source IDs with positive revisions. method
and method_revision are nonblank identities of at most 256 UTF-8 bytes each;
evidence_ref is a nonblank reference of at most 2048 bytes. Control characters
are rejected. Record the actual model/prompt/tool configuration in the referenced
evidence when needed for reproduction. These identifiers are declarations by the
writer; the database does not fetch or verify external evidence.
All sources must exist, match their exact revision, be unexpired and have no
rejected review. Sources may themselves be derived. Each root is limited to eight
dependency edges along any path and 64 distinct source IDs across its transitive
graph. Shared ancestors count once; each node retains the 16-direct-source limit.
Cycles and graphs exceeding these bounds are rejected. Source validation and creation are serialized
with memory mutations. Record, index, idempotency receipt and derived change
entry commit atomically with synchronous WAL durability.
The ordinary command receipt returns action: derived, a new record_id and
revision: 1. Reading the record includes its immutable derivation metadata and
authenticated content author. An identical retry returns the original receipt,
including after a source changes. Refetch current state to establish present
eligibility; a retry receipt is not a current-availability assertion.
Correction and invalidation#
A derived record remains eligible only while every recorded source and its transitive ancestors have the same recorded revision and remain eligible. Source updates, deletions, expiry and review revisions invalidate the dependent record before direct reads, text/filter queries, new embedding attachment, lexical statistics, vector candidates and hybrid combination. This check uses the same request-local storage snapshot as the retrieval data. Requests already in progress may finish on an earlier coherent snapshot; later requests observe committed changes.
Derived content cannot be replaced with an ordinary update command: it returns
409. Create a new derivation from the corrected source revisions instead. A
derived record may be deleted or reviewed. Approval of the derived record does
not override invalid source references; source approval itself advances the source
revision and therefore does not silently revive old conclusions. Every embedded
derived record still needs an external vector bound to its own current revision.
Ordinary create/update records remain independent. The database cannot infer
hidden dependencies in arbitrary text or prevent a writer from copying content
without declaring sources. Applications must select derive whenever they need
this provenance contract.
Dependency work and bounded retrieval#
Query, lexical, semantic and hybrid pages include dependency_work with
records_examined and bytes_examined. These count additional source lookups and
raw source-record bytes read for validation. Missing sources count as one lookup
and zero bytes. Integrity-index bytes and transport/allocator overhead are not
included. This work is separate from candidate scan counters and lexical/hybrid
scan_bytes_limit; do not interpret either counter as total process memory.
Each request caches compact source metadata within its own authorized namespace.
Shared dependencies are read once per request. There is no cross-request or
cross-scope eligibility cache. Work is limited to 4096 distinct dependency lookups
and 16 MiB of source-record bytes per request. Exceeding either limit returns 400
without a partial result; reduce the candidate scan_limit and use the documented
candidate cursor if appropriate. A bounded page remains a ranking over its
examined candidates, not a global top-k guarantee. Oversized individual sources
may require a smaller source representation rather than a smaller candidate page.
Events, history and limitations#
Source mutations produce their own change-feed events. Serving-time invalidation does not rewrite descendants or emit a separate event for each affected derived record. A cache must track reverse dependencies or invalidate the scope when its dependency set is unknown. Clock-driven expiry produces no event: revalidate before use and respect source validity.
Source references identify exact revisions but this API does not retain historical payloads of ordinary memory updates. Preserve required evidence outside this mutable record API or in immutable evidence artifacts. A source revision is not a permanent content-download promise. Metadata does not certify a conclusion's truth, relevance or downstream benefit.
Absent sources return 404; changed or ineligible source revisions return 409. Invalid source lists or graphs exceeding depth/node bounds return 400. Authentication, grants, integrity errors, retry rules and the 64 KiB request body limit follow the durable memory API.
Explain a dependency failure#
A reviewer can call POST /api/v1/memory/eligibility with memory_review and the
exact scope. This uses the same authorization as metadata-only review state;
ordinary read or write authority alone is insufficient.
{
"contract_version": 1,
"scope": {"project_id": "project", "mission_id": null, "agent_id": "agent", "visibility": "shared"},
"record_id": "00000000-0000-4000-8000-000000000042"
}
The response is {contract_version, scope, eligibility}:
| Field | Meaning |
|---|---|
record_id, revision |
Current root identity, including unavailable roots |
eligible |
All serving prerequisites were established in this request |
evaluated_at_millis |
Server time used for validity checks |
first_failure |
Null when eligible; otherwise the first failed root or dependency check |
dependencies_checked |
Distinct source IDs visited for this root, at most 64 |
max_depth_examined |
Maximum dependency path depth encountered or inferred from a previously checked shared subtree |
all_dependencies_checked |
True only when the complete bounded graph was validated |
dependency_work |
Actual additional reads and raw record bytes, using the same work limits as retrieval |
first_failure contains record_id, nullable expected_revision, nullable
actual_revision and reason. Reasons include deleted, expired, rejected,
source_missing, source_revision_changed, dependency_cycle, depth_limit
and node_limit. eligible is the successful internal reason and never a
failure. A reference revision is checked before that source's current disposition:
if a source was rejected at a newer revision, an older reference reports
source_revision_changed. Null actual_revision means it was not established;
it does not mean revision zero.
The diagnostic stops at the first failed check in the stored source-list traversal order. It is not a complete inventory of every issue. A bound failure means the service cannot establish eligibility within its admitted graph contract. It does not assert that an unvisited source is factually wrong. Depth may exceed eight in the diagnostic that reports a bound failure; creation rejects that graph.
No content, vector, method identity, evidence reference or reviewer identity is
copied into this response. A missing root returns 404. Existing deleted, expired,
rejected or source-invalid roots return 200 with eligible: false. The result is
an observation of one snapshot and one time, not a durable authorization token or
a guarantee of eligibility on a later request. Restore or regenerate a conclusion
only after checking its current sources and creating a new derivation.
Traversal caches compact source metadata and validated subtree heights. This avoids repeatedly expanding shared subgraphs while still enforcing the longest path bound when the same subtree appears at different depths. All normal serving paths use this transitive check, including BM25 corpus construction. There is no asynchronous descendant rewrite or eventual-consistency window introduced by a background propagation worker.