Memory consolidation function contract
The consolidation worker (Enterprise) calls a function-mode AgentRuntime once per
axis and workspace, then validates and applies the action list the function
returns. This page lists the request body, every action, and the rejection
reasons. To build a pack, see Write a consolidation pack.
For the policy fields that bind a pack, see MemoryPolicy.
Request
Section titled “Request”The worker sends POST http://<name>.<namespace>.svc.cluster.local:18080/functions/<name>
with Content-Type: application/json. The name and namespace come from the
MemoryPolicy.spec.consolidation.functionRefs.<axis> entry. Port 18080 is the
function’s internal management-plane listener (facade-mgmt). The request
carries Authorization: Bearer <token>, a projected ServiceAccount token for
memory-api with the scheduleAuth.audience audience. The facade admits it when
memory-api’s ServiceAccount is on the function’s
OMNIA_SCHEDULE_AUTH_ALLOWED_SUBJECTS, which the operator sets for every
workspace bound to a policy that names the function.
| Field | Type | Description |
|---|---|---|
axis | string | staleObservations, crossScopeCandidates or entityDuplicateCandidates. |
workspaceID | string | The workspace UID. |
buckets | array | Candidate groups selected by the axis pre-filter. |
gates.minDistinctUserCount | map | Resolved k-anonymity thresholds, keyed agentScoped and userScoped. |
gates.requirePIIRedaction | bool | Whether the PII gate is on. |
Each bucket has a key, an optional stats map, and entries. Each entry has:
| Field | Type | Description |
|---|---|---|
id | string | Memory row ID; on entityDuplicateCandidates, the memory entity ID. Use it in action targetIDs, fromIDs, mergeIDs and canonicalID. |
content | string | The row’s text. |
scope | object | workspaceID, plus agentID and userID when set. |
mutability | string | Only mutable rows can be modified. |
sourceType | string | How the row was written. |
observedAt | timestamp | When the row was observed. Always sent; 0001-01-01T00:00:00Z when unset, as on entityDuplicateCandidates. |
metadata | map of string | Row metadata. Omitted when empty. |
Response
Section titled “Response”The response body must be a JSON array of actions with HTTP status 200. The
action field selects the kind. An unknown action value or a malformed array
fails the whole response, and the worker applies nothing from it.
action | Fields | Required |
|---|---|---|
create_summary | fromIDs, scope, content, metadata | fromIDs non-empty, content non-empty. Sources may have any mutability. |
supersede | targetIDs, withID | Both. |
rescope | targetIDs, newScope, reason | targetIDs non-empty. |
invalidate | targetIDs, validUntil (RFC 3339), reason | targetIDs non-empty, validUntil in the future. |
merge_entities | canonicalID, mergeIDs | Both. Only mergeIDs rows must be mutable. |
discard | targetIDs, reason | targetIDs non-empty. Soft-deletes the rows. |
rescore | targetID, importance, confidence | targetID. Changes one row. |
Rejection reasons
Section titled “Rejection reasons”The validator checks each action independently. A rejected action is skipped and
audited; the others still apply. The reason appears in the audit entry and in the
outcome label of omnia_memory_consolidation_actions_total as rejected_<reason>.
| Reason | Cause |
|---|---|
shape_invalid | A required field in the table above is missing or empty. |
target_unknown | A modified row ID was not in the buckets sent for this call. |
mutability_blocked | A modified row is not mutable. |
institutional_write_blocked | A rescope targets the institutional scope (no agent or user). |
anonymity_below_threshold | A rescope whose newScope has only an agentID or only a userID, and the largest stats.distinctUsers across the buckets sent is below gates.minDistinctUserCount for that scope. Defaults: agentScoped 5, userScoped 1. |
scope_widening_unsupported | safetyGates.maxScopeWidening is set to anything other than workspace. |
scope_outside_workspace | A rescope newScope.workspaceID differs from workspaceID. |
pii_blocked | When requirePIIRedaction is on, the redactor finds PII in content (create_summary) or reason (rescope, invalidate, discard). |
Application
Section titled “Application”Accepted actions are applied one at a time, in order. Each action is atomic, but the actions do not share a transaction: when one fails to apply, the pass stops and earlier actions stay applied. Every applied action records the pack name and time on the rows it touches.