Agent Memory
Platform

Security

The controls that protect memory in Agent Memory — credentials, isolation, least privilege, content screening, secrets handling, erasure and webhook delivery.

Agent memory is a high-value target: it holds decisions, user preferences and sometimes personal data, and whatever it returns is pasted straight into a model's prompt. This page summarizes the controls built into the platform.

Credentials

  • API keys are hashed. Only a SHA-256 hash and a short display prefix are stored; the plaintext is shown once at creation. A database leak never yields usable keys.
  • Revocation is immediate. Revoking a key or a grant invalidates the shared authorization cache, so it bites on the next request on every replica.
  • Keys can expire, and every key is bound to a fixed set of agents. See Authentication.
  • OAuth tokens use the authorization-code flow with rolling refresh tokens (a leaked refresh token stops working after its first use) and support revocation.

Isolation

  • Tenant identity comes only from the credential, never from the request.
  • Cross-tenant and cross-workspace access answers 404, so existence never leaks.
  • Row-level security is forced on tenant tables and fails closed; the runtime database role cannot bypass it. Tenants can be placed in dedicated databases.

See Multi-tenancy.

Least privilege

Three independent layers decide what a caller may do:

  1. Capabilities on the key or grant — read, write, feedback, curate, delete, share, promote. Destructive and widening capabilities (delete, share, promote) are off by default.
  2. Identity binding — a credential can act only as the agents it is bound to, and can name end users only if it is allowed to.
  3. Per-memory visibility — private, agent, user, workspace, tenant — compiled into every query before retrieval runs. Derived memories (episodes, procedures) are never more visible than their most restricted source.

See Identity and visibility.

Memory poisoning and prompt injection

Because recalled memory becomes prompt text, writes are screened before they are stored:

  • Appends are checked for prompt-injection and data-exfiltration patterns — instruction overrides ("ignore previous instructions"), spliced role markers, markdown image beacons and similar. Flagged content is stored quarantined: it is never recalled, merged, consolidated, promoted or shared until a reviewer with the curate capability releases or rejects it (review endpoint).
  • Memory blocks, which are rendered verbatim into every context, reject suspicious content outright.
  • Provenance can't be forged. sourceKind values that mean "the platform produced this" (derived, system) cannot be declared by callers, and platform-owned tags are refused. A declared source never earns more trust than the caller itself would.
  • Governance can't be crowded out. Platform policies and tenant floors are never truncated to fit a token budget; a budget too small to hold them is an error, not a silent drop.

Screening is controlled by the workspace setting screening.enabled (on by default).

Personal data

With screening.pii.enabled (on by default), writes are checked for personal data — national ID and social security numbers, payment cards, phone numbers, email addresses, IBANs. Flagged memories are marked as PII, are never promoted to tenant conventions, and have the detected values redacted in exports. Webhook payload summaries are always redacted.

The activity log never stores query text: it records the query's length and a keyed hash.

Erasure

Deleting a memory destroys its text in the same transaction and then removes every derived copy — session entries, episode events, procedure and abstraction references, history. If some copies cannot be removed immediately, the delete answers pending and a durable obligation is retried until the erasure status reaches complete (or dead, which requires operator attention). Self-hosted operators can re-apply recorded erasures after restoring a backup, so a restore never resurrects deleted data.

Secrets at rest

Secrets the platform must be able to use — webhook signing secrets, a tenant's own LLM provider keys — are encrypted with ASP.NET Core Data Protection. In production the key ring itself must be encrypted with a certificate; the API refuses to start with a plaintext key ring. Webhook secrets are returned in plaintext exactly once, at creation or rotation.

Error hygiene and abuse limits

  • Error responses carry a stable code and a generic detail plus a traceId; exception messages and internal rule names never reach clients.
  • Request bodies are capped (1 MiB by default), list sizes are clamped, and collections are capped.
  • Request rates are limited per tenant (and per IP for anonymous traffic), with optional per-workspace fairness and a concurrency ceiling that sheds load with 503 OVERLOADED.

Outbound calls

  • Webhooks are signed with HMAC-SHA256 over a timestamp and the raw body. Target URLs must be HTTPS and resolve only to public addresses — loopback, private, link-local, CGNAT and cloud-metadata ranges are blocked — and the connection is pinned to the validated IP (defeating DNS rebinding), never follows redirects and times out after 10 seconds. See Webhooks.
  • AI providers. Self-hosted deployments make no paid AI calls unless the operator opts in (Deployment:NoPaidAi), and an air-gapped mode refuses to start if any configured dependency would leave the network.
  • Deterministic recall. By default, recall makes no generative-model calls at all (retrieval.mode: deterministic).

Audit trail

  • Every memory keeps a history of its changes.
  • The workspace change feed records creates, updates, deletes, shares and promotions with the actor and its role — policy fields only, never content.
  • explain shows where any memory came from and who has used it.

Console

The web console uses SameSite cookies plus a required custom header on every write (CSRF defense), supports MFA enforcement per organization (security.requireMfa), and requires acceptance of the current terms before writes.

On this page