Agent Memory

Updating, superseding and deleting

Choose between updating a memory in place, superseding it with a newer one, or deleting it, and understand what each does.

Information changes. Agent Memory lets you change a memory in three different ways; picking the right one keeps history and dependent information correct.

SituationUseWhat happens?
The text of the same information is wrong or incompleteUpdate (update_memory, PUT /v1/memory/{id})The content changes in place; a new revision is created; the validity time does not change.
New information invalidates the oldSupersede (add_memory supersedes=…, supersede_memory)The old memory is not deleted; it is marked as superseded and hidden from default searches.
The information should never be keptDelete (delete_memory, DELETE /v1/memory/{id})The content is redacted and derived copies are cleaned up.

Update

# 1) Read the current version
curl -s "$API/v1/memory/$ID?workspaceId=$WS" -H "Authorization: Bearer $KEY"   # ... "version": 1465395 ...

# 2) Send the version with If-Match
curl -s -i -X PUT "$API/v1/memory/$ID" \
  -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -H 'If-Match: "1465395"' \
  -d "{\"workspaceId\":\"$WS\",\"content\":\"Customer meetings are held on Wednesdays\"}"
# HTTP/1.1 200 OK
# ETag: "1466771"
# {"id":"…","version":1466771}
  • If you send If-Match and the memory changed in the meantime, the write is not applied: 412 precondition_failed with currentVersion in the response. Re-read the memory and try again.
  • Without If-Match, the last writer wins.
  • The content is scanned as on write and re-embedded; an UPDATE is written to history, an update row to the change feed, and an update webhook event is emitted.
  • MCP: update_memory(memoryId, content, version?); take the version value from the get_memory output.
  • Only the content is updated. Type, visibility, tags and time fields are not changed by an update (to widen visibility, see Identity and access).

Supersede

If a new decision or correction invalidates an older memory, say so explicitly:

  • While writing: add_memory(content=…, type="decision", supersedes="<old-id>"). The new memory is written and the old one is immediately treated as superseded. If the target is not visible or is already superseded, nothing is written and the response says why.
  • For two existing memories: supersede_memory(memoryId="<old>", supersededBy="<new>") — for example, when the user says which of two conflicting corrections is valid.

On the superseded memory:

  • supersededAt is stamped and the validity interval is closed (validTo);
  • a REPLACES relationship is added from the new memory to the old one;
  • memories derived from the old memory are flagged for review (reviewState: "stale");
  • the memory is hidden from default searches; it is visible with includeSuperseded: true, and explain_memory shows the chain.

If the superseding memory is deleted, the old memory becomes valid again (unless another live memory supersedes it).

During consolidation the system also performs some supersessions itself (a very similar new decision supersedes the old one; a correction supersedes the decision it contradicts); ambiguous cases are left as open contradictions. See Consolidation, episodes and procedures.

There is no separate REST endpoint for explicit superseding; use the MCP tools for that (for REST clients, consolidation's automatic rules apply).

Delete

curl -s -o /dev/null -w '%{http_code}\n' -X DELETE "$API/v1/memory/$ID?workspaceId=$WS" \
  -H "Authorization: Bearer $KEY"
ResponseMeaning
204Deleted; derived copies were cleaned up too.
202 {"cleanup":"pending"}The memory was redacted; cleanup of derived copies will be retried in the background.
409 deletion_blocked_by_active_dependentsLive memories are derived from this one. Check the blockingDependents list in the response; to delete deliberately, add ?cascade=true.
404The memory doesn't exist or isn't visible to you.
403You lack permission (delete permission, ownership, or it is a tenant-wide rule).

The SDKs return these as deleted, pending, blocked, not_found, forbidden.

What does a delete do?

  1. The deletion is first written to a central erasure ledger (so it can be re-applied after a restore from backup; it contains no content).
  2. In the same operation the memory is redacted: content, summary and embeddings are cleared, and the memory moves to the deleted state.
  3. Derived copies are cleaned up: the copy in the run layer, the related line in the user profile, the run summary, episode events and sentences with the same content, mentions in procedures and abstractions, revisions, and history rows containing values.
  4. If cascade=true was given, dependent memories are not deleted but marked stale; the delete row in the change feed lists the marked ones.

Track the status:

curl -s "$API/v1/memory/$ID/erasure?workspaceId=$WS" -H "Authorization: Bearer $KEY"
# {"memoryId":"…","status":"complete","attempts":0,"erasedAt":"…"}

status: none (no deletion), pending (cleanup in progress), complete, dead (retries exhausted; operator intervention required).

Things to know

  • Entity names extracted from the deleted memory's content, the episode summary the memory appears in, and the dependent memories' own text are not cleaned up by a single-memory delete. To fully remove a person's or project's data, use the project/organization deletion flows. See Data management.
  • There is no single endpoint for bulk deletion by end user (e.g. "delete everything belonging to this userId").
  • Tenant-wide rules cannot be deleted from a workspace connection.

On this page