OneLinersCommand workbench
Guides
AI/ML / Security / Databases & Data

Build short- and long-term agent memory with retention and deletion controls

Design agent working memory, persistent conversation state, compaction, and durable facts as explicit governed application systems with tenant isolation, confirmation, provenance, minimization, TTLs, correction, verified deletion, evaluation, cost monitoring, and rollback that cannot resurrect prohibited memories.

360 min10 stepsHigh-impact changeRevision 2
Save or explore
Save to collectionCreate a collection in the sidebar first.
0 of 10 steps completed
Goal

Give agents useful continuity without turning transcripts or model guesses into an indefinite profile: every memory is typed, attributable, authorized, minimal, expiring, correctable, deletable across provider and application representations, measurable, and recoverable under a security-preserving release process.

Supported environments
  • OpenAI Responses and Conversations APIs current
  • PostgreSQL current supported release
  • OpenAI vector stores current where used
Prerequisites
  • Approved memory purpose and policy Privacy, security, product, records, and service owners define allowed classes, sources, retention, deletion, holds, and subject controls.Review the versioned memory policy registry.
  • Authenticated tenant identity The server resolves opaque tenant and subject IDs plus current permissions without trusting model or client filters.Run positive and cross-tenant negative fixtures.
  • Provider data-control review The team reviewed current OpenAI storage and retention behavior for Responses, Conversations, files, and vector stores used by the design.Compare endpoint choices with the official data-controls table.
  • Isolated release and recovery Schemas, indexes, prompts, policies, deletion workers, and prior release can be tested and restored without production traffic.Run a staging restore with current tombstones.
Operating boundary

OneLiners never runs these steps or stores secrets. Review placeholders, versions, current state, and change-control requirements before using a command.

Full guide

What you will build

System
  • A policy registry and tenant-scoped fact store that separates working turns, persistent provider state, structured checkpoints, confirmed preferences, authoritative facts, and prohibited inferred profiles.
  • A write and retrieval path with structured proposals, confirmation, provenance, validity, minimization before embeddings, bounded context, conflict handling, correction, expiry, tombstones, and provider-aware deletion.
  • A comparison and release system that measures memory utility against privacy, error, latency, token, storage, and cost, then canaries and rolls back without resurrecting old facts.
Observable outcome
  • Users receive continuity from current approved facts while wrong-tenant, stale, deleted, unconfirmed, sensitive, or injected memories never enter context.
  • Operators can distinguish provider conversation state, application working memory, durable facts, vector representations, caches, evaluations, and backups and can prove each lifecycle.
  • Memory remains only where measured task benefit justifies its privacy and operating cost, with explicit correction and deletion controls.

Architecture

How the parts fit together

Authenticated requests create bounded working state through Responses or Conversations. A compaction layer emits structured checkpoints. Durable writes begin as model proposals and become facts only after application validation and appropriate confirmation or authoritative sync. PostgreSQL owns typed tenant-scoped facts and lifecycle events; optional vector search is a derived filtered view. A tombstone service, reconciler, evaluator, aggregate metrics, and release controller govern correction, expiry, deletion, provider cleanup, cost, upgrades, restore, and rollback.

Working context and provider stateCarry bounded task continuity with explicit storage and token behavior.
Compaction checkpointPreserve confirmed facts, decisions, open questions, sources, side effects, uncertainty, and next action under a schema.
Write gate and fact storeValidate proposals, confirmation, provenance, sensitivity, conflicts, validity, retention, and tenant row policy.
Derived retrieval viewReturn a minimal active authorized set and treat memory text as untrusted evidence.
Lifecycle and deletion controllerApply correction, expiry, hold, tombstones, multi-target purge, verification, and restore overlays.
Evaluation and release controlCompare benefit and risk, monitor bounded signals, canary revisions, and restore the complete safe release.
  1. Policy decides whether a turn is ephemeral, compacted, persistent provider state, or eligible for a durable proposal.
  2. The application validates and confirms durable proposals before transactional storage and optional minimized embedding.
  3. Retrieval applies authenticated tenant, subject, state, validity, expiry, confidence, and size constraints before memory enters context.
  4. Corrections supersede, expiry denies, and deletion tombstones immediately before purge and negative verification across every representation.
  5. Evaluation and content-free monitoring govern canary promotion; current lifecycle events overlay every restore and rollback.

Assumptions

  • The application, not the model, owns identity, authorization, retention, and durable writes.
  • The organization can explain the memory feature to users and provide correction, export, and deletion where policy requires.
  • Secrets and high-risk sensitive data can be excluded before persistence and embeddings.
  • Evaluation uses synthetic or governed redacted subjects and does not expose tenant content to broad reviewers.
  • Provider storage behavior is reviewed whenever endpoint or feature choices change.

Key concepts

Working memory
Bounded context needed for the current task or conversation and expired or compacted promptly.
Long-term memory
Durable typed application facts retained across sessions under explicit purpose, provenance, access, correction, and deletion.
Compaction
Replacing older working items with a structured checkpoint while preserving required state and lineage.
Memory proposal
Schema-valid candidate fact emitted by a model that has no persistence authority until the application validates and confirms it.
Validity versus retention
How long a fact is true versus how long its representation may remain stored; they require separate timestamps.
Tombstone
Minimal durable denial state preventing deleted identity from retrieval, replay, restore, or rollback.

Before you copy

Values used in this guide

{{databaseUrl}}secret

PostgreSQL connection URI supplied securely to psql.

Example: postgresql://agent_app@db.internal/agent_state
{{memoryMigration}}

Reviewed SQL migration for fact and lifecycle schema.

Example: /srv/agent-memory/migrations/001_memory.sql
{{tenantId}}

Opaque authenticated tenant identity supplied by trusted application state.

Example: tenant-a
{{subjectId}}

Opaque authenticated memory subject identity, never an email address.

Example: subj-7f3
{{memoryId}}

Stable UUID of the exact durable fact being managed.

Example: 018f6c20-1111-7000-8000-000000000001
{{model}}

Pinned evaluated OpenAI model ID.

Example: gpt-5.4-mini
{{compactionSchema}}

Versioned JSON Schema for structured checkpoints.

Example: /srv/agent-memory/schemas/checkpoint-v3.json
{{conversationId}}

Exact persistent OpenAI Conversation ID authorized for deletion.

Example: conv_abc123
{{vectorStoreId}}

Exact OpenAI vector store containing the derived memory file.

Example: vs_abc123
{{vectorFileId}}

Exact vector-store file identity mapped to this memory representation.

Example: file_abc123
{{deletionEventId}}

Idempotent authorized deletion-request event written before external cleanup.

Example: delete-771
{{deletionVerifiedEventId}}

Unique lifecycle event written after all online targets verify absence.

Example: delete-771-verified
{{memoryEvalPath}}

Path to real pytest memory fixtures in the application repository.

Example: tests/agent_memory
{{memoryEvalReport}}

JUnit report path bound to the candidate release.

Example: artifacts/memory-r4.xml
{{metricsPort}}

Loopback aggregate application metrics port.

Example: 9464

Security and production boundaries

  • Memory is application state, not an implicit model capability. Store only information required for a declared purpose, bind it to an authenticated opaque tenant and subject, and make authorization, retention, correction, export, and deletion deterministic application controls.
  • Never let user text or model output directly mark itself as durable truth. Validate schema, provenance, consent or policy basis, sensitivity, confidence, conflicts, and write authorization before persistence; consequential facts require an authoritative source or human confirmation.
  • Minimize before storing or embedding. Exclude secrets, credentials, payment data, health or identity details outside the approved purpose, and treat summaries, embeddings, indexes, caches, backups, and evaluation copies as protected derived representations.
  • A deleted or revoked memory must be denied immediately and removed from every online representation, then verified by stable identity. Historical backups remain restricted until policy expiry and must consume current tombstones before any restore becomes searchable.

Stop before continuing if

  • Stop if the product cannot explain which facts become short-term versus long-term memory, why they are needed, how long they remain, and how the subject can correct or delete them.
  • Stop if a memory read or write can cross tenant boundaries, accept client-selected authorization filters, or use email addresses and names as broadly visible keys.
  • Stop if model-generated summaries are treated as authoritative without provenance, confirmation, conflict handling, and an explicit path to abstain.
  • Stop if restore or rollback can resurrect deleted, expired, quarantined, or permission-revoked memories.
01

decision

Define the memory contract and data map

read-only

Separate working context, conversation state, compacted summaries, durable user preferences, authoritative account facts, learned task patterns, and prohibited data. For every class define purpose, source of truth, write authority, tenant and subject key, sensitivity, consent or policy basis, retention trigger and TTL, retrieval scope, correction, export, deletion deadline, legal-hold behavior, backup treatment, cost budget, and quality metric. Document which OpenAI objects and which application stores contain state; provider storage and your database do not share a deletion lifecycle automatically.

Why this step matters

Memory architecture starts with policy because convenient persistence can silently become indefinite profiling. A complete data map makes later API, database, vector, backup, and user controls consistent.

What to understand

Use opaque HMAC or internal subject identifiers instead of email in product tables.

Prohibit credentials and high-risk sensitive classes unless a separately reviewed use requires them.

Define usefulness and error metrics per class so retention is justified by evidence rather than possibility.

System changes

  • Creates a reviewed policy registry; it does not yet store user content.

Syntax explained

retention_days
Maximum ordinary lifetime after the class-specific trigger.
write_authority
Who or what may turn a proposed fact into durable state.
delete_sla_hours
Deadline for verified online removal after an eligible request.
Command
Fill variables0/1 ready

Values stay on this page and are never sent or saved.

psql {{databaseUrl}} -c "SELECT memory_class, purpose, retention_days, write_authority, delete_sla_hours FROM memory_policy ORDER BY memory_class;"
Example output / evidence
 memory_class | purpose                | retention_days | write_authority    | delete_sla_hours
--------------+------------------------+----------------+--------------------+-----------------
 working      | active task context    |              1 | application        |               1
 preference   | user-confirmed defaults|            180 | confirmed-user     |              24
 account_fact | current service state  |             30 | authoritative-sync |               4

Checkpoint: Checkpoint: Define the memory contract and data map

psql {{databaseUrl}} -c "SELECT memory_class, purpose, retention_days, write_authority, delete_sla_hours FROM memory_policy ORDER BY memory_class;"

Continue whenEvery state class has declared purpose, authority, retention, deletion, privacy, quality, and cost boundaries.

Stop whenAny class is described merely as useful context with no source, expiry, subject control, or deletion target inventory.

If this step fails

Memory storage cost grows without corresponding utility.

Likely causeEvery turn becomes a vector, duplicate facts are not merged, expired stores remain, or retrieval usage is unmeasured.

Safe checks
  • Group storage by tenant, type, age, and hit rate.
  • Find stable-ID duplicates.
  • Review vector-store expiration and backup retention.

ResolutionRestrict durable write classes, deduplicate by fact identity, expire eligible data, and prove quality before retaining low-value memory.

Security notes

  • Memory is application state, not an implicit model capability. Store only information required for a declared purpose, bind it to an authenticated opaque tenant and subject, and make authorization, retention, correction, export, and deletion deterministic application controls.
  • Never let user text or model output directly mark itself as durable truth. Validate schema, provenance, consent or policy basis, sensitivity, confidence, conflicts, and write authorization before persistence; consequential facts require an authoritative source or human confirmation.
  • Minimize before storing or embedding. Exclude secrets, credentials, payment data, health or identity details outside the approved purpose, and treat summaries, embeddings, indexes, caches, backups, and evaluation copies as protected derived representations.
  • A deleted or revoked memory must be denied immediately and removed from every online representation, then verified by stable identity. Historical backups remain restricted until policy expiry and must consume current tombstones before any restore becomes searchable.

Alternatives

  • Run the same decision with synthetic data and an isolated tenant before changing production retention, memory selection, tracing, sampling, or evaluation.
  • Keep the previous schema, prompt, policy, exporter, dashboard, and release manifest available so recovery does not require reconstructing an unknown configuration.

Stop conditions

  • Stop if the product cannot explain which facts become short-term versus long-term memory, why they are needed, how long they remain, and how the subject can correct or delete them.
  • Stop if a memory read or write can cross tenant boundaries, accept client-selected authorization filters, or use email addresses and names as broadly visible keys.
  • Stop if model-generated summaries are treated as authoritative without provenance, confirmation, conflict handling, and an explicit path to abstain.
  • Stop if restore or rollback can resurrect deleted, expired, quarantined, or permission-revoked memories.
02

config

Create tenant-scoped versioned memory tables with row security

caution

Store durable memory as typed facts rather than transcript blobs. Include stable memory ID, tenant, opaque subject, class, normalized value or encrypted payload reference, provenance, confidence, validity interval, policy revision, state, created and expiry timestamps, superseded-by identity, and deletion event. Enable and force PostgreSQL row-level security for normal application roles. Write an append-only lifecycle event for proposal, confirmation, correction, expiry, quarantine, and deletion.

Why this step matters

Typed, versioned facts make conflict, correction, expiry, and deletion observable. Database row security provides defense in depth before the same tenant predicate is projected into retrieval indexes.

What to understand

Application code must set tenant context from authenticated state inside the transaction.

Table owners and BYPASSRLS roles need separate audited maintenance procedures.

Keep raw transcripts outside durable facts unless their specific retention purpose is approved.

System changes

  • Creates stateful database schema and fail-closed tenant row policy.

Syntax explained

FORCE ROW LEVEL SECURITY
Subjects ordinary table-owner access to policies.
valid_until / expires_at
Separates factual validity from storage retention.
superseded_by
Links corrections without silently overwriting provenance.
File {{memoryMigration}}
Configuration
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE TABLE agent_memory (
  memory_id uuid PRIMARY KEY,
  tenant_id text NOT NULL,
  subject_id text NOT NULL,
  fact_key text NOT NULL,
  memory_class text NOT NULL CHECK (memory_class IN ('working','preference','account_fact')),
  value_json jsonb,
  encrypted_payload_ref text,
  source_type text NOT NULL,
  source_ref text NOT NULL,
  confidence numeric(4,3) NOT NULL CHECK (confidence BETWEEN 0 AND 1),
  policy_revision text NOT NULL,
  valid_from timestamptz NOT NULL,
  valid_until timestamptz,
  expires_at timestamptz NOT NULL,
  state text NOT NULL CHECK (state IN ('proposed','active','superseded','expired','quarantined','deleted')),
  superseded_by uuid REFERENCES agent_memory(memory_id),
  deletion_event_id text,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now(),
  CHECK (
    state IN ('expired','deleted')
    OR (value_json IS NOT NULL)::integer + (encrypted_payload_ref IS NOT NULL)::integer = 1
  ),
  CHECK (valid_until IS NULL OR valid_until >= valid_from),
  UNIQUE (tenant_id, subject_id, fact_key, valid_from)
);
CREATE TABLE agent_memory_lifecycle (
  event_id text PRIMARY KEY,
  memory_id uuid NOT NULL REFERENCES agent_memory(memory_id),
  tenant_id text NOT NULL,
  subject_id text NOT NULL,
  event_type text NOT NULL CHECK (event_type IN ('proposed','confirmed','corrected','expired','quarantined','deletion_requested','deleted')),
  source_ref text NOT NULL,
  policy_revision text NOT NULL,
  reason_code text NOT NULL,
  value_digest text,
  occurred_at timestamptz NOT NULL DEFAULT now()
);
CREATE TABLE agent_memory_representations (
  memory_id uuid NOT NULL REFERENCES agent_memory(memory_id),
  target text NOT NULL CHECK (target IN ('postgres','vector','cache','provider_conversation')),
  external_id text,
  state text NOT NULL CHECK (state IN ('active','deletion_pending','deleted','verified')),
  deleted_at timestamptz,
  verified_at timestamptz,
  PRIMARY KEY (memory_id, target)
);
CREATE TABLE memory_release_members (
  release_id text NOT NULL,
  memory_id uuid NOT NULL REFERENCES agent_memory(memory_id),
  tenant_id text NOT NULL,
  included_at timestamptz NOT NULL DEFAULT now(),
  PRIMARY KEY (release_id, memory_id)
);
CREATE FUNCTION reject_memory_lifecycle_mutation() RETURNS trigger
LANGUAGE plpgsql AS $$ BEGIN RAISE EXCEPTION 'agent_memory_lifecycle is append-only'; END $$;
CREATE TRIGGER agent_memory_lifecycle_append_only
BEFORE UPDATE OR DELETE ON agent_memory_lifecycle
FOR EACH ROW EXECUTE FUNCTION reject_memory_lifecycle_mutation();
ALTER TABLE agent_memory ENABLE ROW LEVEL SECURITY;
ALTER TABLE agent_memory FORCE ROW LEVEL SECURITY;
ALTER TABLE agent_memory_lifecycle ENABLE ROW LEVEL SECURITY;
ALTER TABLE agent_memory_lifecycle FORCE ROW LEVEL SECURITY;
ALTER TABLE agent_memory_representations ENABLE ROW LEVEL SECURITY;
ALTER TABLE agent_memory_representations FORCE ROW LEVEL SECURITY;
ALTER TABLE memory_release_members ENABLE ROW LEVEL SECURITY;
ALTER TABLE memory_release_members FORCE ROW LEVEL SECURITY;
CREATE POLICY memory_tenant ON agent_memory
  USING (tenant_id = current_setting('app.tenant_id', true))
  WITH CHECK (tenant_id = current_setting('app.tenant_id', true));
CREATE POLICY memory_lifecycle_tenant ON agent_memory_lifecycle
  USING (tenant_id = current_setting('app.tenant_id', true))
  WITH CHECK (tenant_id = current_setting('app.tenant_id', true));
CREATE POLICY memory_representation_tenant ON agent_memory_representations
  USING (EXISTS (
    SELECT 1 FROM agent_memory m
    WHERE m.memory_id = agent_memory_representations.memory_id
      AND m.tenant_id = current_setting('app.tenant_id', true)
  ))
  WITH CHECK (EXISTS (
    SELECT 1 FROM agent_memory m
    WHERE m.memory_id = agent_memory_representations.memory_id
      AND m.tenant_id = current_setting('app.tenant_id', true)
  ));
CREATE POLICY memory_release_tenant ON memory_release_members
  USING (tenant_id = current_setting('app.tenant_id', true))
  WITH CHECK (tenant_id = current_setting('app.tenant_id', true));
Example output / evidence
CREATE EXTENSION
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE FUNCTION
CREATE TRIGGER
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
ALTER TABLE
CREATE POLICY
CREATE POLICY
CREATE POLICY
CREATE POLICY
policies=4 lifecycle_append_only=true negative_tenant_cases=48 mismatches=0

Checkpoint: Checkpoint: Create tenant-scoped versioned memory tables with row security

Continue whenApplication roles cannot read or write another tenant and every fact has source, validity, state, and expiry.

Stop whenTenant context is client-controlled, the application bypasses row security, or facts lack stable identity and provenance.

If this step fails

The agent recalls a preference belonging to another user.

Likely causeTenant or subject scope is missing from the lookup, cache key, vector filter, or database policy.

Safe checks
  • Disable memory injection.
  • Compare authenticated identity with returned opaque IDs.
  • Run cross-tenant negative fixtures across cache and vector paths.

ResolutionTreat as a security incident, restore the last fail-closed release, invalidate affected caches, and add database plus retrieval isolation tests.

Security notes

  • Memory is application state, not an implicit model capability. Store only information required for a declared purpose, bind it to an authenticated opaque tenant and subject, and make authorization, retention, correction, export, and deletion deterministic application controls.
  • Never let user text or model output directly mark itself as durable truth. Validate schema, provenance, consent or policy basis, sensitivity, confidence, conflicts, and write authorization before persistence; consequential facts require an authoritative source or human confirmation.
  • Minimize before storing or embedding. Exclude secrets, credentials, payment data, health or identity details outside the approved purpose, and treat summaries, embeddings, indexes, caches, backups, and evaluation copies as protected derived representations.
  • A deleted or revoked memory must be denied immediately and removed from every online representation, then verified by stable identity. Historical backups remain restricted until policy expiry and must consume current tombstones before any restore becomes searchable.

Alternatives

  • Run the same decision with synthetic data and an isolated tenant before changing production retention, memory selection, tracing, sampling, or evaluation.
  • Keep the previous schema, prompt, policy, exporter, dashboard, and release manifest available so recovery does not require reconstructing an unknown configuration.

Stop conditions

  • Stop if the product cannot explain which facts become short-term versus long-term memory, why they are needed, how long they remain, and how the subject can correct or delete them.
  • Stop if a memory read or write can cross tenant boundaries, accept client-selected authorization filters, or use email addresses and names as broadly visible keys.
  • Stop if model-generated summaries are treated as authoritative without provenance, confirmation, conflict handling, and an explicit path to abstain.
  • Stop if restore or rollback can resurrect deleted, expired, quarantined, or permission-revoked memories.
03

config

Use bounded short-term Responses state deliberately

read-only

Choose stateless requests with store false when the application supplies an explicitly minimized working set, or use previous_response_id or a Conversation when persistent provider state is justified. OpenAI documents that Responses are stored by default unless store is false, while Conversation objects persist until deleted. Do not confuse provider state with your durable memory policy. Re-send developer instructions because previous_response_id does not carry prior instructions automatically, and monitor that prior input tokens remain billable.

Why this step matters

Short-term continuity is a product and retention decision. Explicit store behavior and bounded context prevent accidental persistence and reveal the token cost of long chains.

What to understand

Never put API keys or user secrets in shell history; production code obtains keys from a secret manager.

Use Conversations only when their until-deleted application state matches policy and deletion orchestration exists.

Cap turns or tokens and compact before the context window becomes an operational failure.

System changes

  • Creates one non-stored API response; it does not create a persistent Conversation.

Syntax explained

store:false
Disables storage of the generated Response object for later retrieval, subject to current endpoint controls.
developer message
Restates trusted instructions for this request rather than relying on a previous response.
usage
Returns input, output, and total tokens for cost and budget monitoring.
Configuration
Fill variables0/1 ready

Values stay on this page and are never sent or saved.

curl -sS https://api.openai.com/v1/responses -H "Authorization: Bearer $OPENAI_API_KEY" -H "Content-Type: application/json" -d '{"model":"{{model}}","store":false,"input":[{"role":"developer","content":"Use only supplied task context."},{"role":"user","content":"Summarize the three open actions."}]}' | jq '{id,status,usage}'
Example output / evidence
{"id":"resp_abc123","status":"completed","usage":{"input_tokens":31,"output_tokens":46,"total_tokens":77}}

Checkpoint: Checkpoint: Use bounded short-term Responses state deliberately

curl -sS https://api.openai.com/v1/responses -H "Authorization: Bearer $OPENAI_API_KEY" -H "Content-Type: application/json" -d '{"model":"{{model}}","store":false,"input":[{"role":"developer","content":"Use only supplied task context."},{"role":"user","content":"Summarize the three open actions."}]}' | jq '{id,status,usage}'

Continue whenThe response completes, reports token usage, and no application code treats its ID as durable memory.

Stop whenProvider retention requirements are unknown, instructions depend silently on prior state, or sensitive content is placed in shell history.

If this step fails

Short-term context becomes too long and expensive.

Likely causeTurns are appended indefinitely, compaction never runs, or summaries duplicate raw history.

Safe checks
  • Measure input and cached tokens per turn.
  • List active items and summary boundaries.
  • Compare answer quality before and after deterministic pruning.

ResolutionApply a tested window and compaction policy, preserve critical open state, and delete superseded short-term items according to retention.

Security notes

  • Memory is application state, not an implicit model capability. Store only information required for a declared purpose, bind it to an authenticated opaque tenant and subject, and make authorization, retention, correction, export, and deletion deterministic application controls.
  • Never let user text or model output directly mark itself as durable truth. Validate schema, provenance, consent or policy basis, sensitivity, confidence, conflicts, and write authorization before persistence; consequential facts require an authoritative source or human confirmation.
  • Minimize before storing or embedding. Exclude secrets, credentials, payment data, health or identity details outside the approved purpose, and treat summaries, embeddings, indexes, caches, backups, and evaluation copies as protected derived representations.
  • A deleted or revoked memory must be denied immediately and removed from every online representation, then verified by stable identity. Historical backups remain restricted until policy expiry and must consume current tombstones before any restore becomes searchable.

Alternatives

  • Run the same decision with synthetic data and an isolated tenant before changing production retention, memory selection, tracing, sampling, or evaluation.
  • Keep the previous schema, prompt, policy, exporter, dashboard, and release manifest available so recovery does not require reconstructing an unknown configuration.

Stop conditions

  • Stop if the product cannot explain which facts become short-term versus long-term memory, why they are needed, how long they remain, and how the subject can correct or delete them.
  • Stop if a memory read or write can cross tenant boundaries, accept client-selected authorization filters, or use email addresses and names as broadly visible keys.
  • Stop if model-generated summaries are treated as authoritative without provenance, confirmation, conflict handling, and an explicit path to abstain.
  • Stop if restore or rollback can resurrect deleted, expired, quarantined, or permission-revoked memories.
04

config

Compact working memory into a structured, reviewable checkpoint

read-only

When a task crosses the working-token budget, create a structured checkpoint containing durable task facts, confirmed decisions, unresolved questions, obligations, cited source IDs, tool side effects, uncertainty, and the next safe action. Exclude conversational style and redundant text. Validate against a schema, compare with the pre-compaction fixture, and retain the raw working window only for its short retention. A compacted summary is derived data with its own lineage, not unquestioned truth.

Why this step matters

Structured compaction bounds latency and cost while preserving the state required to continue safely. Schema and fixture comparison make omissions visible before raw context expires.

What to understand

Never compact secrets into a longer-lived summary.

Preserve uncertainty and conflicts instead of choosing a neat but unsupported fact.

Version the compaction prompt, schema, model, and source-item IDs.

System changes

  • Creates a derived checkpoint and schedules superseded working items for policy-based expiry.

Syntax explained

required
Fields whose loss would make resumed work unsafe or incomplete.
source_id
Provenance link used to verify and later delete derived statements.
side_effects
Completed external actions that must not be repeated after resume.
File {{compactionSchema}}
Configuration
{"type":"object","required":["confirmed_facts","open_questions","decisions","side_effects","source_ids","next_action"],"properties":{"confirmed_facts":{"type":"array","items":{"type":"object","required":["fact","source_id","confidence"]}},"open_questions":{"type":"array"},"decisions":{"type":"array"},"side_effects":{"type":"array"},"source_ids":{"type":"array"},"next_action":{"type":"string"}}}
Example output / evidence
schema=PASS input_tokens=11842 checkpoint_tokens=913 compression=92.3% unresolved_items_before=4 unresolved_items_after=4 source_ids_preserved=7 side_effects_preserved=2

Checkpoint: Checkpoint: Compact working memory into a structured, reviewable checkpoint

Continue whenThe compacted checkpoint passes schema and preserves every reviewed unresolved item, decision, source, and side effect.

Stop whenThe model summary cannot be compared with source items, uncertainty disappears, or secrets would gain a longer retention.

If this step fails

Compaction drops an unresolved requirement.

Likely causeThe summary schema omitted open decisions, obligations, provenance, or uncertainty.

Safe checks
  • Compare pre-compaction items with the compacted record.
  • Run frozen unresolved-task fixtures.
  • Inspect summary version and token boundary.

ResolutionRestore the uncompacted checkpoint, revise the structured summary schema, and rerun evaluation before enabling compaction.

Security notes

  • Memory is application state, not an implicit model capability. Store only information required for a declared purpose, bind it to an authenticated opaque tenant and subject, and make authorization, retention, correction, export, and deletion deterministic application controls.
  • Never let user text or model output directly mark itself as durable truth. Validate schema, provenance, consent or policy basis, sensitivity, confidence, conflicts, and write authorization before persistence; consequential facts require an authoritative source or human confirmation.
  • Minimize before storing or embedding. Exclude secrets, credentials, payment data, health or identity details outside the approved purpose, and treat summaries, embeddings, indexes, caches, backups, and evaluation copies as protected derived representations.
  • A deleted or revoked memory must be denied immediately and removed from every online representation, then verified by stable identity. Historical backups remain restricted until policy expiry and must consume current tombstones before any restore becomes searchable.

Alternatives

  • Run the same decision with synthetic data and an isolated tenant before changing production retention, memory selection, tracing, sampling, or evaluation.
  • Keep the previous schema, prompt, policy, exporter, dashboard, and release manifest available so recovery does not require reconstructing an unknown configuration.

Stop conditions

  • Stop if the product cannot explain which facts become short-term versus long-term memory, why they are needed, how long they remain, and how the subject can correct or delete them.
  • Stop if a memory read or write can cross tenant boundaries, accept client-selected authorization filters, or use email addresses and names as broadly visible keys.
  • Stop if model-generated summaries are treated as authoritative without provenance, confirmation, conflict handling, and an explicit path to abstain.
  • Stop if restore or rollback can resurrect deleted, expired, quarantined, or permission-revoked memories.
05

config

Gate durable memory writes through proposal and confirmation

caution

Have the model emit a structured memory proposal, never a direct database write. The application validates allowed class, subject, provenance, sensitivity, confidence, conflict, TTL, and caller authority. User preferences require explicit confirmation in the user interface; authoritative account facts come from a trusted service sync; inferred traits remain prohibited or short-lived unless separately reviewed. Insert the fact and lifecycle event transactionally, then generate embeddings only from minimized approved content.

Why this step matters

A proposal boundary prevents hallucinations and prompt injection from becoming durable profile data. Transactional confirmation preserves source and lifecycle evidence with the fact.

What to understand

Validate JSON against a closed schema and reject unknown fields.

Do not let confidence substitute for authoritative confirmation.

Deduplicate or supersede by stable fact identity rather than accumulating contradictory copies.

System changes

  • Persists one confirmed tenant-scoped preference with fixed expiry.

Syntax explained

SET LOCAL app.tenant_id
Binds database row policy to authenticated transaction state.
source_type/source_ref
Records why the write was trusted and how it can be audited.
expires_at
Schedules retention independently of whether the fact remains valid.
Configuration
Fill variables0/4 ready

Values stay on this page and are never sent or saved.

psql {{databaseUrl}} -v ON_ERROR_STOP=1 -c "BEGIN; SET LOCAL app.tenant_id='{{tenantId}}'; INSERT INTO agent_memory(memory_id,tenant_id,subject_id,fact_key,memory_class,value_json,source_type,source_ref,confidence,policy_revision,valid_from,expires_at,state) VALUES ('{{memoryId}}','{{tenantId}}','{{subjectId}}','timezone','preference','{\"timezone\":\"Europe/Warsaw\"}','user-confirmation','ui-confirmation-771',1.000,'memory-policy-v3',now(),now()+interval '180 days','active'); INSERT INTO agent_memory_lifecycle(event_id,memory_id,tenant_id,subject_id,event_type,source_ref,policy_revision,reason_code,value_digest) VALUES ('event-771','{{memoryId}}','{{tenantId}}','{{subjectId}}','confirmed','ui-confirmation-771','memory-policy-v3','explicit_user_confirmation',encode(digest('{\"timezone\":\"Europe/Warsaw\"}','sha256'),'hex')); INSERT INTO agent_memory_representations(memory_id,target,external_id,state) VALUES ('{{memoryId}}','postgres','{{memoryId}}','active'); COMMIT;"
Example output / evidence
BEGIN
SET
INSERT 0 1
INSERT 0 1
INSERT 0 1
COMMIT

Checkpoint: Checkpoint: Gate durable memory writes through proposal and confirmation

psql {{databaseUrl}} -v ON_ERROR_STOP=1 -c "BEGIN; SET LOCAL app.tenant_id='{{tenantId}}'; INSERT INTO agent_memory(memory_id,tenant_id,subject_id,fact_key,memory_class,value_json,source_type,source_ref,confidence,policy_revision,valid_from,expires_at,state) VALUES ('{{memoryId}}','{{tenantId}}','{{subjectId}}','timezone','preference','{\"timezone\":\"Europe/Warsaw\"}','user-confirmation','ui-confirmation-771',1.000,'memory-policy-v3',now(),now()+interval '180 days','active'); INSERT INTO agent_memory_lifecycle(event_id,memory_id,tenant_id,subject_id,event_type,source_ref,policy_revision,reason_code,value_digest) VALUES ('event-771','{{memoryId}}','{{tenantId}}','{{subjectId}}','confirmed','ui-confirmation-771','memory-policy-v3','explicit_user_confirmation',encode(digest('{\"timezone\":\"Europe/Warsaw\"}','sha256'),'hex')); INSERT INTO agent_memory_representations(memory_id,target,external_id,state) VALUES ('{{memoryId}}','postgres','{{memoryId}}','active'); COMMIT;"

Continue whenThe fact is visible only to its tenant, carries confirmation provenance and expiry, and has one lifecycle event.

Stop whenThe proposal contains prohibited data, source is untrusted, conflict is unresolved, or confirmation cannot be proven.

If this step fails

The agent stores a hallucinated fact as durable memory.

Likely causeModel output bypassed validation, provenance, confidence, or confirmation.

Safe checks
  • Inspect the write proposal and source event.
  • Compare with authoritative data.
  • Review the memory-write policy and confirmation trace.

ResolutionQuarantine the fact, correct dependent summaries, require structured proposals and trusted confirmation for durable writes.

Security notes

  • Memory is application state, not an implicit model capability. Store only information required for a declared purpose, bind it to an authenticated opaque tenant and subject, and make authorization, retention, correction, export, and deletion deterministic application controls.
  • Never let user text or model output directly mark itself as durable truth. Validate schema, provenance, consent or policy basis, sensitivity, confidence, conflicts, and write authorization before persistence; consequential facts require an authoritative source or human confirmation.
  • Minimize before storing or embedding. Exclude secrets, credentials, payment data, health or identity details outside the approved purpose, and treat summaries, embeddings, indexes, caches, backups, and evaluation copies as protected derived representations.
  • A deleted or revoked memory must be denied immediately and removed from every online representation, then verified by stable identity. Historical backups remain restricted until policy expiry and must consume current tombstones before any restore becomes searchable.

Alternatives

  • Run the same decision with synthetic data and an isolated tenant before changing production retention, memory selection, tracing, sampling, or evaluation.
  • Keep the previous schema, prompt, policy, exporter, dashboard, and release manifest available so recovery does not require reconstructing an unknown configuration.

Stop conditions

  • Stop if the product cannot explain which facts become short-term versus long-term memory, why they are needed, how long they remain, and how the subject can correct or delete them.
  • Stop if a memory read or write can cross tenant boundaries, accept client-selected authorization filters, or use email addresses and names as broadly visible keys.
  • Stop if model-generated summaries are treated as authoritative without provenance, confirmation, conflict handling, and an explicit path to abstain.
  • Stop if restore or rollback can resurrect deleted, expired, quarantined, or permission-revoked memories.
06

verification

Retrieve minimal authorized memories with freshness and conflict rules

read-only

Resolve tenant and opaque subject from authenticated state, query active and unexpired structured facts first, then optionally vector-search approved narrative memory using identical pre-retrieval filters. Limit the number and bytes injected. Prefer authoritative current facts over inference, retain source and validity, surface unresolved conflicts, and exclude low-confidence or stale records. Delimit memory as untrusted data so stored prompt injection cannot modify tools or policy.

Why this step matters

Retrieval is where stored data becomes model influence. Exact tenant, state, time, provenance, and size controls reduce disclosure, staleness, injection, latency, and token cost.

What to understand

Do not put subject IDs into metric labels with unbounded cardinality.

Cache only with tenant, subject, policy, ACL, and memory revision in the key.

Verify that a user correction supersedes older records in both structured and vector paths.

System changes

  • Reads a bounded authorized memory set and does not modify persistent state.

Syntax explained

state/expires_at/valid_until
Excludes deleted, quarantined, expired, and factually obsolete records.
LIMIT 20
Bounds context volume but must be evaluated for task quality.
ORDER BY
Provides deterministic preference among current versions while conflicts remain explicit.
Command
Fill variables0/3 ready

Values stay on this page and are never sent or saved.

psql {{databaseUrl}} -c "BEGIN; SET LOCAL app.tenant_id='{{tenantId}}'; SELECT memory_id,memory_class,value_json,source_type,valid_from,valid_until,expires_at FROM agent_memory WHERE subject_id='{{subjectId}}' AND state='active' AND expires_at>now() AND (valid_until IS NULL OR valid_until>now()) ORDER BY memory_class,valid_from DESC LIMIT 20; COMMIT;"
Example output / evidence
memory_id                           | memory_class | value_json                       | source_type
------------------------------------+--------------+----------------------------------+------------------
018f6c20-1111-7000-8000-000000000001| preference   | {"timezone":"Europe/Warsaw"} | user-confirmation
(1 row)

Checkpoint: Checkpoint: Retrieve minimal authorized memories with freshness and conflict rules

psql {{databaseUrl}} -c "BEGIN; SET LOCAL app.tenant_id='{{tenantId}}'; SELECT memory_id,memory_class,value_json,source_type,valid_from,valid_until,expires_at FROM agent_memory WHERE subject_id='{{subjectId}}' AND state='active' AND expires_at>now() AND (valid_until IS NULL OR valid_until>now()) ORDER BY memory_class,valid_from DESC LIMIT 20; COMMIT;"

Continue whenOnly current authorized facts enter the memory envelope and cross-tenant, stale, deleted, and injection fixtures return none.

Stop whenFiltering occurs after retrieval, cache scope is incomplete, or memory text can override trusted instructions.

If this step fails

Long-term retrieval is relevant but stale.

Likely causeTTL, validity interval, source revision, or freshness ranking is absent.

Safe checks
  • Compare current time and source revision with memory metadata.
  • Inspect expired-record filtering.
  • Run stale-versus-current conflict fixtures.

ResolutionFilter expired facts before retrieval, refresh authoritative facts, preserve conflict provenance, and abstain when no current evidence exists.

Security notes

  • Memory is application state, not an implicit model capability. Store only information required for a declared purpose, bind it to an authenticated opaque tenant and subject, and make authorization, retention, correction, export, and deletion deterministic application controls.
  • Never let user text or model output directly mark itself as durable truth. Validate schema, provenance, consent or policy basis, sensitivity, confidence, conflicts, and write authorization before persistence; consequential facts require an authoritative source or human confirmation.
  • Minimize before storing or embedding. Exclude secrets, credentials, payment data, health or identity details outside the approved purpose, and treat summaries, embeddings, indexes, caches, backups, and evaluation copies as protected derived representations.
  • A deleted or revoked memory must be denied immediately and removed from every online representation, then verified by stable identity. Historical backups remain restricted until policy expiry and must consume current tombstones before any restore becomes searchable.

Alternatives

  • Run the same decision with synthetic data and an isolated tenant before changing production retention, memory selection, tracing, sampling, or evaluation.
  • Keep the previous schema, prompt, policy, exporter, dashboard, and release manifest available so recovery does not require reconstructing an unknown configuration.

Stop conditions

  • Stop if the product cannot explain which facts become short-term versus long-term memory, why they are needed, how long they remain, and how the subject can correct or delete them.
  • Stop if a memory read or write can cross tenant boundaries, accept client-selected authorization filters, or use email addresses and names as broadly visible keys.
  • Stop if model-generated summaries are treated as authoritative without provenance, confirmation, conflict handling, and an explicit path to abstain.
  • Stop if restore or rollback can resurrect deleted, expired, quarantined, or permission-revoked memories.
07

warning

Implement correction, expiry, and verified deletion across representations

danger

A correction creates a new version and supersedes the old stable fact; it does not silently rewrite provenance. An expiry job moves eligible facts to expired and blocks retrieval before asynchronous purge. This concrete deletion path authenticates scope, appends a tombstone, clears the PostgreSQL payload, deletes the mapped OpenAI vector-store file, unlinks the Redis subject cache, deletes the named OpenAI Conversation, and verifies all four online representations before appending completion. If the product also creates summaries, exports, analytics, evaluation copies, backups, or another provider object, add them to the representation table and orchestration before claiming deletion coverage.

Why this step matters

Memory exists in multiple application and provider objects. Immediate denial plus per-target purge and verification makes user control truthful despite asynchronous consistency.

What to understand

Deleting an OpenAI Conversation does not delete unrelated application memory automatically.

Keep a minimal tombstone under approved retention to prevent restore resurrection.

Deletions under valid hold are recorded as pending and execute after authorized release.

System changes

  • Irreversibly clears the named PostgreSQL payload, OpenAI vector-store file, Redis cache key, and OpenAI Conversation after a durable deletion-request event.
  • Keeps a minimal content-free tombstone and per-target verification evidence to prevent restore or retry resurrection.

Syntax explained

PostgreSQL tombstone transaction
Denies application retrieval and clears stored payload before eventually consistent external deletion begins.
DELETE vector-store file and Conversation
Deletes the exact mapped OpenAI derived file and persistent Conversation rather than relying on application state.
Redis UNLINK and EXISTS
Removes the exact scoped cache key asynchronously and verifies it no longer exists.
Authorization
Uses a server-held API credential; never expose it to a browser or shell history.
Command
Fill variables0/9 ready

Values stay on this page and are never sent or saved.

bash -eu -o pipefail -c 'psql {{databaseUrl}} -v ON_ERROR_STOP=1 -c "BEGIN; SET LOCAL app.tenant_id='"'"'{{tenantId}}'"'"'; INSERT INTO agent_memory_lifecycle(event_id,memory_id,tenant_id,subject_id,event_type,source_ref,policy_revision,reason_code) VALUES ('"'"'{{deletionEventId}}'"'"','"'"'{{memoryId}}'"'"','"'"'{{tenantId}}'"'"','"'"'{{subjectId}}'"'"','"'"'deletion_requested'"'"','"'"'subject-request'"'"','"'"'memory-policy-v3'"'"','"'"'verified_subject_request'"'"') ON CONFLICT (event_id) DO NOTHING; UPDATE agent_memory SET state='"'"'deleted'"'"', value_json=NULL, encrypted_payload_ref=NULL, deletion_event_id='"'"'{{deletionEventId}}'"'"', expires_at=now(), updated_at=now() WHERE memory_id='"'"'{{memoryId}}'"'"' AND tenant_id='"'"'{{tenantId}}'"'"'; INSERT INTO agent_memory_representations(memory_id,target,external_id,state) VALUES ('"'"'{{memoryId}}'"'"','"'"'postgres'"'"','"'"'{{memoryId}}'"'"','"'"'deletion_pending'"'"'), ('"'"'{{memoryId}}'"'"','"'"'vector'"'"','"'"'{{vectorStoreId}}/{{vectorFileId}}'"'"','"'"'deletion_pending'"'"'), ('"'"'{{memoryId}}'"'"','"'"'cache'"'"','"'"'memory:{{tenantId}}:{{subjectId}}'"'"','"'"'deletion_pending'"'"'), ('"'"'{{memoryId}}'"'"','"'"'provider_conversation'"'"','"'"'{{conversationId}}'"'"','"'"'deletion_pending'"'"') ON CONFLICT (memory_id,target) DO UPDATE SET external_id=excluded.external_id,state='"'"'deletion_pending'"'"',deleted_at=NULL,verified_at=NULL; COMMIT;"; curl -fsS -X DELETE "https://api.openai.com/v1/vector_stores/{{vectorStoreId}}/files/{{vectorFileId}}" -H "Authorization: Bearer $OPENAI_API_KEY" | jq -e ".deleted == true"; redis-cli -h "$MEMORY_CACHE_HOST" -p "${MEMORY_CACHE_PORT:-6379}" UNLINK "memory:{{tenantId}}:{{subjectId}}" | grep -Eq "^[01]$"; curl -fsS -X DELETE "https://api.openai.com/v1/conversations/{{conversationId}}" -H "Authorization: Bearer $OPENAI_API_KEY" | jq -e ".deleted == true"; test "$(curl -sS -o /dev/null -w "%{http_code}" "https://api.openai.com/v1/vector_stores/{{vectorStoreId}}/files/{{vectorFileId}}" -H "Authorization: Bearer $OPENAI_API_KEY")" = 404; test "$(redis-cli -h "$MEMORY_CACHE_HOST" -p "${MEMORY_CACHE_PORT:-6379}" EXISTS "memory:{{tenantId}}:{{subjectId}}")" = 0; test "$(curl -sS -o /dev/null -w "%{http_code}" "https://api.openai.com/v1/conversations/{{conversationId}}" -H "Authorization: Bearer $OPENAI_API_KEY")" = 404; psql {{databaseUrl}} -v ON_ERROR_STOP=1 -c "BEGIN; SET LOCAL app.tenant_id='"'"'{{tenantId}}'"'"'; UPDATE agent_memory_representations SET state='"'"'verified'"'"', deleted_at=now(), verified_at=now() WHERE memory_id='"'"'{{memoryId}}'"'"'; INSERT INTO agent_memory_lifecycle(event_id,memory_id,tenant_id,subject_id,event_type,source_ref,policy_revision,reason_code) VALUES ('"'"'{{deletionVerifiedEventId}}'"'"','"'"'{{memoryId}}'"'"','"'"'{{tenantId}}'"'"','"'"'{{subjectId}}'"'"','"'"'deleted'"'"','"'"'multi-target-verification'"'"','"'"'memory-policy-v3'"'"','"'"'all_online_targets_absent'"'"'); COMMIT; SELECT memory_id,state,value_json,encrypted_payload_ref,deletion_event_id FROM agent_memory WHERE memory_id='"'"'{{memoryId}}'"'"';"'
Example output / evidence
BEGIN
SET
INSERT 0 1
UPDATE 1
UPDATE 4
COMMIT
true
1
true
BEGIN
SET
UPDATE 4
INSERT 0 1
COMMIT
memory_id=018f6c20-1111-7000-8000-000000000001 state=deleted value_json=NULL encrypted_payload_ref=NULL deletion_event_id=delete-771

Checkpoint: Checkpoint: Implement correction, expiry, and verified deletion across representations

bash -eu -o pipefail -c 'psql {{databaseUrl}} -v ON_ERROR_STOP=1 -c "BEGIN; SET LOCAL app.tenant_id='"'"'{{tenantId}}'"'"'; INSERT INTO agent_memory_lifecycle(event_id,memory_id,tenant_id,subject_id,event_type,source_ref,policy_revision,reason_code) VALUES ('"'"'{{deletionEventId}}'"'"','"'"'{{memoryId}}'"'"','"'"'{{tenantId}}'"'"','"'"'{{subjectId}}'"'"','"'"'deletion_requested'"'"','"'"'subject-request'"'"','"'"'memory-policy-v3'"'"','"'"'verified_subject_request'"'"') ON CONFLICT (event_id) DO NOTHING; UPDATE agent_memory SET state='"'"'deleted'"'"', value_json=NULL, encrypted_payload_ref=NULL, deletion_event_id='"'"'{{deletionEventId}}'"'"', expires_at=now(), updated_at=now() WHERE memory_id='"'"'{{memoryId}}'"'"' AND tenant_id='"'"'{{tenantId}}'"'"'; INSERT INTO agent_memory_representations(memory_id,target,external_id,state) VALUES ('"'"'{{memoryId}}'"'"','"'"'postgres'"'"','"'"'{{memoryId}}'"'"','"'"'deletion_pending'"'"'), ('"'"'{{memoryId}}'"'"','"'"'vector'"'"','"'"'{{vectorStoreId}}/{{vectorFileId}}'"'"','"'"'deletion_pending'"'"'), ('"'"'{{memoryId}}'"'"','"'"'cache'"'"','"'"'memory:{{tenantId}}:{{subjectId}}'"'"','"'"'deletion_pending'"'"'), ('"'"'{{memoryId}}'"'"','"'"'provider_conversation'"'"','"'"'{{conversationId}}'"'"','"'"'deletion_pending'"'"') ON CONFLICT (memory_id,target) DO UPDATE SET external_id=excluded.external_id,state='"'"'deletion_pending'"'"',deleted_at=NULL,verified_at=NULL; COMMIT;"; curl -fsS -X DELETE "https://api.openai.com/v1/vector_stores/{{vectorStoreId}}/files/{{vectorFileId}}" -H "Authorization: Bearer $OPENAI_API_KEY" | jq -e ".deleted == true"; redis-cli -h "$MEMORY_CACHE_HOST" -p "${MEMORY_CACHE_PORT:-6379}" UNLINK "memory:{{tenantId}}:{{subjectId}}" | grep -Eq "^[01]$"; curl -fsS -X DELETE "https://api.openai.com/v1/conversations/{{conversationId}}" -H "Authorization: Bearer $OPENAI_API_KEY" | jq -e ".deleted == true"; test "$(curl -sS -o /dev/null -w "%{http_code}" "https://api.openai.com/v1/vector_stores/{{vectorStoreId}}/files/{{vectorFileId}}" -H "Authorization: Bearer $OPENAI_API_KEY")" = 404; test "$(redis-cli -h "$MEMORY_CACHE_HOST" -p "${MEMORY_CACHE_PORT:-6379}" EXISTS "memory:{{tenantId}}:{{subjectId}}")" = 0; test "$(curl -sS -o /dev/null -w "%{http_code}" "https://api.openai.com/v1/conversations/{{conversationId}}" -H "Authorization: Bearer $OPENAI_API_KEY")" = 404; psql {{databaseUrl}} -v ON_ERROR_STOP=1 -c "BEGIN; SET LOCAL app.tenant_id='"'"'{{tenantId}}'"'"'; UPDATE agent_memory_representations SET state='"'"'verified'"'"', deleted_at=now(), verified_at=now() WHERE memory_id='"'"'{{memoryId}}'"'"'; INSERT INTO agent_memory_lifecycle(event_id,memory_id,tenant_id,subject_id,event_type,source_ref,policy_revision,reason_code) VALUES ('"'"'{{deletionVerifiedEventId}}'"'"','"'"'{{memoryId}}'"'"','"'"'{{tenantId}}'"'"','"'"'{{subjectId}}'"'"','"'"'deleted'"'"','"'"'multi-target-verification'"'"','"'"'memory-policy-v3'"'"','"'"'all_online_targets_absent'"'"'); COMMIT; SELECT memory_id,state,value_json,encrypted_payload_ref,deletion_event_id FROM agent_memory WHERE memory_id='"'"'{{memoryId}}'"'"';"'

Continue whenPostgreSQL retains no payload, the vector-store file and Conversation return not found, the scoped cache key is absent, all four target rows are verified, and a content-free completion event is appended.

Stop whenIdentity or authority is uncertain, a hold applies, the target inventory is incomplete, or one provider result would be misreported as complete deletion.

If this step fails

Conversation deletion succeeds but application memory remains.

Likely causeProvider conversation state and application long-term memory have separate lifecycle paths.

Safe checks
  • List linked opaque conversation and memory IDs.
  • Inspect deletion workflow target acknowledgements.
  • Check whether user-facing wording promised both.

ResolutionMake deletion scope explicit, orchestrate both provider and application deletion where requested, and report completion only after each target verifies.

Security notes

  • Memory is application state, not an implicit model capability. Store only information required for a declared purpose, bind it to an authenticated opaque tenant and subject, and make authorization, retention, correction, export, and deletion deterministic application controls.
  • Never let user text or model output directly mark itself as durable truth. Validate schema, provenance, consent or policy basis, sensitivity, confidence, conflicts, and write authorization before persistence; consequential facts require an authoritative source or human confirmation.
  • Minimize before storing or embedding. Exclude secrets, credentials, payment data, health or identity details outside the approved purpose, and treat summaries, embeddings, indexes, caches, backups, and evaluation copies as protected derived representations.
  • A deleted or revoked memory must be denied immediately and removed from every online representation, then verified by stable identity. Historical backups remain restricted until policy expiry and must consume current tombstones before any restore becomes searchable.

Alternatives

  • Run the same decision with synthetic data and an isolated tenant before changing production retention, memory selection, tracing, sampling, or evaluation.
  • Keep the previous schema, prompt, policy, exporter, dashboard, and release manifest available so recovery does not require reconstructing an unknown configuration.

Stop conditions

  • Stop if the product cannot explain which facts become short-term versus long-term memory, why they are needed, how long they remain, and how the subject can correct or delete them.
  • Stop if a memory read or write can cross tenant boundaries, accept client-selected authorization filters, or use email addresses and names as broadly visible keys.
  • Stop if model-generated summaries are treated as authoritative without provenance, confirmation, conflict handling, and an explicit path to abstain.
  • Stop if restore or rollback can resurrect deleted, expired, quarantined, or permission-revoked memories.
08

verification

Evaluate memory utility, error, privacy, latency, and cost by class

read-only

Use a frozen set of continuations and cross-tenant negative cases. Compare no-memory, short-term-only, and short-plus-long-term releases. Measure task success, factual recall, correction use, stale-memory rate, unsupported-memory rate, conflict handling, deletion and isolation failures, input tokens, cached tokens, latency, vector reads, storage, and cost. Inspect every security failure and enough quality wins and losses to validate the metric. A memory feature should be removed if measured benefit does not justify privacy and operating cost.

Why this step matters

Memory makes answers feel personalized even when it is wrong, so demos are unreliable. Controlled comparisons quantify benefit and expose stale, unsupported, private, slow, and expensive behavior.

What to understand

Keep evaluation subjects synthetic or governed and redacted.

Report by memory class and task because one useful preference can hide harmful inferred traits.

Treat one cross-tenant or deletion violation as a blocker.

System changes

  • Runs read-only evaluation fixtures and writes a report; it does not change user memory.

Syntax explained

python -m pytest
Executes real deterministic application fixtures through the installed Python test runner.
--junitxml
Produces machine-readable results for release gating.
Command
Fill variables0/2 ready

Values stay on this page and are never sent or saved.

python -m pytest -q {{memoryEvalPath}} --junitxml={{memoryEvalReport}}
Example output / evidence
................................................................ [100%]
64 passed in 18.42s
memory_release=mem-r4 utility_delta=+0.083 stale_rate=0.000 cross_tenant_leaks=0 deletion_failures=0 p95_added_ms=37 added_tokens_p50=184

Checkpoint: Checkpoint: Evaluate memory utility, error, privacy, latency, and cost by class

python -m pytest -q {{memoryEvalPath}} --junitxml={{memoryEvalReport}}

Continue whenThe candidate provides measured task benefit with zero security/deletion violations and accepted latency, token, storage, and cost.

Stop whenOnly subjective examples exist, candidate outputs label their own truth, or critical privacy classes lack fixtures.

If this step fails

Memory storage cost grows without corresponding utility.

Likely causeEvery turn becomes a vector, duplicate facts are not merged, expired stores remain, or retrieval usage is unmeasured.

Safe checks
  • Group storage by tenant, type, age, and hit rate.
  • Find stable-ID duplicates.
  • Review vector-store expiration and backup retention.

ResolutionRestrict durable write classes, deduplicate by fact identity, expire eligible data, and prove quality before retaining low-value memory.

Security notes

  • Memory is application state, not an implicit model capability. Store only information required for a declared purpose, bind it to an authenticated opaque tenant and subject, and make authorization, retention, correction, export, and deletion deterministic application controls.
  • Never let user text or model output directly mark itself as durable truth. Validate schema, provenance, consent or policy basis, sensitivity, confidence, conflicts, and write authorization before persistence; consequential facts require an authoritative source or human confirmation.
  • Minimize before storing or embedding. Exclude secrets, credentials, payment data, health or identity details outside the approved purpose, and treat summaries, embeddings, indexes, caches, backups, and evaluation copies as protected derived representations.
  • A deleted or revoked memory must be denied immediately and removed from every online representation, then verified by stable identity. Historical backups remain restricted until policy expiry and must consume current tombstones before any restore becomes searchable.

Alternatives

  • Run the same decision with synthetic data and an isolated tenant before changing production retention, memory selection, tracing, sampling, or evaluation.
  • Keep the previous schema, prompt, policy, exporter, dashboard, and release manifest available so recovery does not require reconstructing an unknown configuration.

Stop conditions

  • Stop if the product cannot explain which facts become short-term versus long-term memory, why they are needed, how long they remain, and how the subject can correct or delete them.
  • Stop if a memory read or write can cross tenant boundaries, accept client-selected authorization filters, or use email addresses and names as broadly visible keys.
  • Stop if model-generated summaries are treated as authoritative without provenance, confirmation, conflict handling, and an explicit path to abstain.
  • Stop if restore or rollback can resurrect deleted, expired, quarantined, or permission-revoked memories.
09

verification

Monitor lifecycle deadlines, drift, and cost without logging content

read-only

Export counters and histograms for proposals, confirmed and rejected writes, active and expired facts, retrieval hits and misses, correction conflicts, compaction ratio, deletion age and overdue targets, ACL denials, redaction quarantine, vector-store bytes, injected tokens, latency, and estimated cost. Use bounded class, release, and outcome labels—never user, tenant, query, fact, or memory IDs. Audit through access-controlled opaque event records. Alert on missed deletion deadlines, stale-memory spikes, isolation fixtures, storage growth, and utility regression.

Why this step matters

Lifecycle controls fail asynchronously, and cost grows gradually. Content-free bounded telemetry detects those failures without turning monitoring into another memory database.

What to understand

Keep an authoritative price and model revision outside high-cardinality labels.

Test alerts with synthetic overdue deletion and stale-fact cases.

Restrict audit-event access and retention separately from aggregate metrics.

System changes

  • Exposes aggregate private metrics and enables lifecycle, quality-proxy, and cost alerts.

Syntax explained

127.0.0.1
Keeps the metrics endpoint local or behind a separately controlled private collector.
bounded labels
Prevents user data disclosure and metric-cardinality failure.
Command
Fill variables0/1 ready

Values stay on this page and are never sent or saved.

curl -fsS http://127.0.0.1:{{metricsPort}}/metrics | grep -E '^agent_memory_(deletion_overdue|active|retrieval_latency_seconds|injected_tokens|estimated_cost)' | head
Example output / evidence
agent_memory_active{class="preference",release="mem-r4"} 18420
agent_memory_deletion_overdue{target="vector"} 0
agent_memory_injected_tokens_sum{class="preference"} 3384021
agent_memory_estimated_cost_usd_total{component="embedding"} 82.14

Checkpoint: Checkpoint: Monitor lifecycle deadlines, drift, and cost without logging content

curl -fsS http://127.0.0.1:{{metricsPort}}/metrics | grep -E '^agent_memory_(deletion_overdue|active|retrieval_latency_seconds|injected_tokens|estimated_cost)' | head

Continue whenMetrics contain no subject content or identifiers and synthetic lifecycle, privacy, and cost alerts fire with correct release context.

Stop whenMetrics expose text or identifiers, deletion age cannot be observed, or dashboards cannot distinguish memory releases.

If this step fails

A deleted memory still affects answers.

Likely causeOnly the canonical row was removed while embeddings, cache, summary, conversation, or backup restore state remains.

Safe checks
  • Search all representations by stable ID.
  • Inspect tombstone acknowledgements.
  • Repeat negative semantic probes after consistency windows.

ResolutionKeep an immediate retrieval deny, purge every online representation, verify absence, and apply the tombstone during future restore.

Security notes

  • Memory is application state, not an implicit model capability. Store only information required for a declared purpose, bind it to an authenticated opaque tenant and subject, and make authorization, retention, correction, export, and deletion deterministic application controls.
  • Never let user text or model output directly mark itself as durable truth. Validate schema, provenance, consent or policy basis, sensitivity, confidence, conflicts, and write authorization before persistence; consequential facts require an authoritative source or human confirmation.
  • Minimize before storing or embedding. Exclude secrets, credentials, payment data, health or identity details outside the approved purpose, and treat summaries, embeddings, indexes, caches, backups, and evaluation copies as protected derived representations.
  • A deleted or revoked memory must be denied immediately and removed from every online representation, then verified by stable identity. Historical backups remain restricted until policy expiry and must consume current tombstones before any restore becomes searchable.

Alternatives

  • Run the same decision with synthetic data and an isolated tenant before changing production retention, memory selection, tracing, sampling, or evaluation.
  • Keep the previous schema, prompt, policy, exporter, dashboard, and release manifest available so recovery does not require reconstructing an unknown configuration.

Stop conditions

  • Stop if the product cannot explain which facts become short-term versus long-term memory, why they are needed, how long they remain, and how the subject can correct or delete them.
  • Stop if a memory read or write can cross tenant boundaries, accept client-selected authorization filters, or use email addresses and names as broadly visible keys.
  • Stop if model-generated summaries are treated as authoritative without provenance, confirmation, conflict handling, and an explicit path to abstain.
  • Stop if restore or rollback can resurrect deleted, expired, quarantined, or permission-revoked memories.
10

decision

Canary upgrades and rehearse security-preserving rollback

caution

Version schema, memory policy, compaction prompt, write validator, embedding, retrieval filters, ranking, cache namespace, metrics, and deletion worker as one release. Backfill to an isolated generation and compare parity. Shadow synthetic or governed traffic, then canary stable subjects with automatic abort on cross-tenant access, deletion failure, unsupported durable write, stale-memory threshold, latency, token, or cost budget. Roll back behavior and derived indexes together while applying current corrections, expiries, tombstones, and ACL revocations to the former generation.

Why this step matters

Memory rollback is dangerous because old data may no longer be permitted. Release coupling and a security-ledger overlay restore quality without undoing user control.

What to understand

Never use a database snapshot switch as rollback without replaying current lifecycle events.

Keep canary assignment stable and expose attempted, failed, and aborted denominators.

Retain the failed release for diagnosis only within policy.

System changes

  • Reads rollback safety evidence; production promotion occurs only after the canary and separate change approval.

Syntax explained

BEGIN/ROLLBACK
Runs the safety query without committing state changes.
forbidden states
Proves the former release contains no identities now prohibited from retrieval.
Command
Fill variables0/2 ready

Values stay on this page and are never sent or saved.

psql {{databaseUrl}} -v ON_ERROR_STOP=1 -c "BEGIN; SET LOCAL app.tenant_id='{{tenantId}}'; SELECT count(*) AS forbidden_restore_rows FROM agent_memory WHERE state IN ('deleted','expired','quarantined') AND memory_id IN (SELECT memory_id FROM memory_release_members WHERE release_id='mem-r3'); ROLLBACK;"
Example output / evidence
BEGIN
SET
 forbidden_restore_rows
-----------------------
                     0
(1 row)
ROLLBACK

Checkpoint: Checkpoint: Canary upgrades and rehearse security-preserving rollback

psql {{databaseUrl}} -v ON_ERROR_STOP=1 -c "BEGIN; SET LOCAL app.tenant_id='{{tenantId}}'; SELECT count(*) AS forbidden_restore_rows FROM agent_memory WHERE state IN ('deleted','expired','quarantined') AND memory_id IN (SELECT memory_id FROM memory_release_members WHERE release_id='mem-r3'); ROLLBACK;"

Continue whenCanary meets quality, privacy, latency, and cost gates, and rollback restores behavior without reviving forbidden memory.

Stop whenReleases cannot be distinguished, current lifecycle events cannot overlay the former generation, or automatic abort is unavailable.

If this step fails

Rollback restores good answers but resurrects old memories.

Likely causeHistorical database or vector snapshots were exposed without current tombstones and ACL revocations.

Safe checks
  • Keep restored state isolated.
  • Compare security-ledger high-water marks.
  • Run deleted, expired, and cross-tenant probes.

ResolutionReplay current tombstones, expiry, corrections, and revocations before traffic; never trade prohibited resurrection for availability.

Security notes

  • Memory is application state, not an implicit model capability. Store only information required for a declared purpose, bind it to an authenticated opaque tenant and subject, and make authorization, retention, correction, export, and deletion deterministic application controls.
  • Never let user text or model output directly mark itself as durable truth. Validate schema, provenance, consent or policy basis, sensitivity, confidence, conflicts, and write authorization before persistence; consequential facts require an authoritative source or human confirmation.
  • Minimize before storing or embedding. Exclude secrets, credentials, payment data, health or identity details outside the approved purpose, and treat summaries, embeddings, indexes, caches, backups, and evaluation copies as protected derived representations.
  • A deleted or revoked memory must be denied immediately and removed from every online representation, then verified by stable identity. Historical backups remain restricted until policy expiry and must consume current tombstones before any restore becomes searchable.

Alternatives

  • Run the same decision with synthetic data and an isolated tenant before changing production retention, memory selection, tracing, sampling, or evaluation.
  • Keep the previous schema, prompt, policy, exporter, dashboard, and release manifest available so recovery does not require reconstructing an unknown configuration.

Stop conditions

  • Stop if the product cannot explain which facts become short-term versus long-term memory, why they are needed, how long they remain, and how the subject can correct or delete them.
  • Stop if a memory read or write can cross tenant boundaries, accept client-selected authorization filters, or use email addresses and names as broadly visible keys.
  • Stop if model-generated summaries are treated as authoritative without provenance, confirmation, conflict handling, and an explicit path to abstain.
  • Stop if restore or rollback can resurrect deleted, expired, quarantined, or permission-revoked memories.

Finish line

Verification checklist

Tenant and policy isolationpython -m pytest -q {{memoryEvalPath}} -k 'tenant or policy or prohibited'All positive cases pass and cross-tenant, denied, malformed, prohibited-data, and model-direct-write cases fail closed.
Correction and deletionpython -m pytest -q {{memoryEvalPath}} -k 'correction or deletion or expiry or restore'Old facts are superseded, every online representation is absent after deletion, and restore keeps current tombstones.
Utility and budgetpython -m pytest -q {{memoryEvalPath}} --junitxml={{memoryEvalReport}}Memory improves the accepted tasks with zero blockers and stays inside token, latency, storage, and cost budgets.
Content-free monitoringcurl -fsS http://127.0.0.1:{{metricsPort}}/metrics | grep '^agent_memory_'Lifecycle and cost metrics are present with bounded labels and no user content or identifiers.

Recovery guidance

Common problems and safe checks

The agent recalls a preference belonging to another user.

Likely causeTenant or subject scope is missing from the lookup, cache key, vector filter, or database policy.

Safe checks
  • Disable memory injection.
  • Compare authenticated identity with returned opaque IDs.
  • Run cross-tenant negative fixtures across cache and vector paths.

ResolutionTreat as a security incident, restore the last fail-closed release, invalidate affected caches, and add database plus retrieval isolation tests.

A deleted memory still affects answers.

Likely causeOnly the canonical row was removed while embeddings, cache, summary, conversation, or backup restore state remains.

Safe checks
  • Search all representations by stable ID.
  • Inspect tombstone acknowledgements.
  • Repeat negative semantic probes after consistency windows.

ResolutionKeep an immediate retrieval deny, purge every online representation, verify absence, and apply the tombstone during future restore.

The agent stores a hallucinated fact as durable memory.

Likely causeModel output bypassed validation, provenance, confidence, or confirmation.

Safe checks
  • Inspect the write proposal and source event.
  • Compare with authoritative data.
  • Review the memory-write policy and confirmation trace.

ResolutionQuarantine the fact, correct dependent summaries, require structured proposals and trusted confirmation for durable writes.

Short-term context becomes too long and expensive.

Likely causeTurns are appended indefinitely, compaction never runs, or summaries duplicate raw history.

Safe checks
  • Measure input and cached tokens per turn.
  • List active items and summary boundaries.
  • Compare answer quality before and after deterministic pruning.

ResolutionApply a tested window and compaction policy, preserve critical open state, and delete superseded short-term items according to retention.

Compaction drops an unresolved requirement.

Likely causeThe summary schema omitted open decisions, obligations, provenance, or uncertainty.

Safe checks
  • Compare pre-compaction items with the compacted record.
  • Run frozen unresolved-task fixtures.
  • Inspect summary version and token boundary.

ResolutionRestore the uncompacted checkpoint, revise the structured summary schema, and rerun evaluation before enabling compaction.

A user correction is ignored and the older fact wins retrieval.

Likely causeVersions are unlinked, ranking favors recency incorrectly, or old embeddings were not superseded.

Safe checks
  • Inspect lineage and validity intervals.
  • Search by stable fact identity.
  • Compare current canonical and vector revisions.

ResolutionCreate an explicit supersession event, tombstone old derived records, reindex the current fact, and verify negative retrieval for the former value.

Memory search returns secrets that should never have been stored.

Likely causeMinimization ran after persistence or detectors missed a credential pattern.

Safe checks
  • Quarantine the affected tenant index.
  • Trace raw, summary, vector, cache, and logs.
  • Run approved secret fixtures without copying values.

ResolutionPurge affected representations, rotate exposed credentials, move minimization before write, and expand the reviewed detector suite.

Conversation deletion succeeds but application memory remains.

Likely causeProvider conversation state and application long-term memory have separate lifecycle paths.

Safe checks
  • List linked opaque conversation and memory IDs.
  • Inspect deletion workflow target acknowledgements.
  • Check whether user-facing wording promised both.

ResolutionMake deletion scope explicit, orchestrate both provider and application deletion where requested, and report completion only after each target verifies.

Long-term retrieval is relevant but stale.

Likely causeTTL, validity interval, source revision, or freshness ranking is absent.

Safe checks
  • Compare current time and source revision with memory metadata.
  • Inspect expired-record filtering.
  • Run stale-versus-current conflict fixtures.

ResolutionFilter expired facts before retrieval, refresh authoritative facts, preserve conflict provenance, and abstain when no current evidence exists.

Memory storage cost grows without corresponding utility.

Likely causeEvery turn becomes a vector, duplicate facts are not merged, expired stores remain, or retrieval usage is unmeasured.

Safe checks
  • Group storage by tenant, type, age, and hit rate.
  • Find stable-ID duplicates.
  • Review vector-store expiration and backup retention.

ResolutionRestrict durable write classes, deduplicate by fact identity, expire eligible data, and prove quality before retaining low-value memory.

A legal hold silently prevents deletion forever.

Likely causeHold scope, review date, release authority, or deferred deletion is missing.

Safe checks
  • Inspect the restricted hold record.
  • Confirm access remains unchanged.
  • Check pending deletion and review schedule.

ResolutionFollow the authorized records process, preserve only scoped data, retain the pending purge, and execute it after approved release.

Rollback restores good answers but resurrects old memories.

Likely causeHistorical database or vector snapshots were exposed without current tombstones and ACL revocations.

Safe checks
  • Keep restored state isolated.
  • Compare security-ledger high-water marks.
  • Run deleted, expired, and cross-tenant probes.

ResolutionReplay current tombstones, expiry, corrections, and revocations before traffic; never trade prohibited resurrection for availability.

After the procedure

Alternatives and next steps

Consider these alternatives

  • Use stateless Responses with store false and reconstruct only a minimized current task context when persistent state is unnecessary.
  • Use a persistent Conversation for bounded continuity when its until-deleted lifecycle and deletion API match the product policy.
  • Retrieve authoritative profile data on demand from its source system rather than duplicating it as agent memory.
  • Disable long-term memory for sensitive or low-value workflows where evaluation cannot justify the privacy and operating burden.

Operate it safely

  • Add weekly reconciliation for facts, vectors, caches, conversations, tombstones, expiries, correction conflicts, and backup restore overlays.
  • Track utility and stale-memory rates by allowed class, and retire classes whose measured benefit no longer justifies retention.
  • Run quarterly cross-tenant, prompt-injection, correction, deletion, legal-hold, compaction-loss, provider-cleanup, and rollback exercises.
  • Review OpenAI endpoint retention and storage controls before adopting any new stateful tool or capability.

Reference

Frequently asked questions

Is previous_response_id long-term memory?

No. It chains response context. Durable product memory still needs explicit application purpose, access, retention, correction, and deletion.

Does store false erase my own database?

No. It controls storage of that API Response object. Your database, logs, vectors, caches, and backups have independent lifecycles.

Can the model decide what to remember?

It may propose a typed fact, but the application validates class, provenance, sensitivity, conflict, TTL, and authorization; important facts need confirmation or an authoritative source.

Should every conversation turn be embedded?

Usually not. It increases privacy, duplication, storage, and retrieval noise. Persist only evaluated classes with clear purpose.

How do corrections work?

Create a new version linked to the former fact, stop retrieving the old version, update derived indexes, and preserve auditable provenance under policy.

Can a backup contain deleted memory?

Possibly under an approved immutable-backup policy until expiry. Restrict it and replay current tombstones before any restore is exposed.

What if memory adds no measurable benefit?

Remove or narrow it. Personalization aesthetics do not justify indefinite data retention, token cost, and security risk.

What must rollback preserve?

All current corrections, expiries, tombstones, holds, quarantines, and ACL revocations, even when restoring an older behavior or index generation.

Recovery

Rollback

Disable durable writes, return retrieval and compaction to the previous complete release, invalidate release caches, and apply all current corrections, expiries, tombstones, holds, and ACL revocations before the former generation can serve.

  1. Stop new durable proposals and preserve opaque release, event, alert, and evaluation evidence without copying user content.
  2. Route reads to the last accepted policy, schema, compaction, retrieval, and cache release while keeping immediate tombstone denial active.
  3. Replay all lifecycle events newer than the restored generation and rebuild its derived vector index when parity is uncertain.
  4. Run cross-tenant, prohibited-data, correction, expiry, deletion, compaction, utility, latency, and cost smoke tests.
  5. Resume gradually and require a new immutable revision after the failed behavior is represented in the evaluation set.

Evidence

Sources and review

Verified 2026-07-24Review due 2026-10-22
OpenAI conversation state guideofficialOpenAI data controls and endpoint retentionofficialOpenAI Retrieval guide: vector stores and expirationofficialOpenAI reliable agents memory and compaction cookbookofficialPostgreSQL row security policiesofficial