# Memory Guard

> What Memory Guard rejects, what it replaces with placeholders before saving, and what the agent sees in each case.

Memory Guard is the MMW server's protective layer that every record passes through before it is saved. It has two jobs: **reject** attempts to poison an agent's memory, and **scrub** secrets.

On this page you will learn:

1. which records are rejected outright and what the agent sees;
2. which secrets are replaced with placeholders and what a placeholder looks like;
3. where else the same rules apply.

## Rejection: protection against memory poisoning

Agents read memory, so a record can become a way to plant instructions for future sessions. Memory Guard rejects record text that looks like such an attempt:

- requests to ignore previous instructions or prior context;
- attempts to override the system prompt;
- instructions to exfiltrate data to an external address;
- instructions to send passwords, secrets or tokens somewhere.

Empty records are rejected as well.

What the agent sees is an error from the `remember` tool:

```text
Memory rejected by Security Guard: Memory poisoning detected: matching pattern '…'
```

The record is **not saved**. If you genuinely need to record such an event ("the task contained a prompt injection attempt"), describe it in your own words without quoting the malicious phrase.

The poisoning check applies to the record text (`content`). The other fields go through the secret scrubbing described below.

## Secret scrubbing

A secret in a record does not cause a rejection: the record is saved, but the secret itself is replaced with a placeholder. Every persisted field is checked: `content`, `source`, `source_id`, `source_hash`, `source_revision`, `fact_key`.

What is recognized, by category:

| Category | Examples |
| --- | --- |
| Private keys | PEM blocks, PuTTY keys, including truncated ones |
| Connection strings | The password in database URIs and in `user:password@host` addresses — only the password is masked |
| Authorization headers | `Authorization: Bearer …`, `Basic …` |
| LLM provider keys | OpenAI, Anthropic, Groq, xAI, Hugging Face, Replicate and similar |
| Developer platforms | GitHub, GitLab, Atlassian, npm and PyPI tokens |
| Cloud | AWS, Google Cloud, Azure, DigitalOcean, HashiCorp Vault and others |
| Messaging | Slack, Telegram bots, SendGrid, Twilio |
| Payments and SaaS | Stripe, Shopify, Linear, Notion |
| MMW keys | Keys in the `mmw_…` format |
| Signed tokens | JWT |
| Assignments | `password=…`, `API_KEY: …` and similar secret-name/value pairs |

A placeholder looks like this:

```text
[REDACTED:<rule>:<8-character hash>]
```

Example. The agent tries to save:

```text
Test database: postgres://app:<password>@db.internal:5432/app
```

What ends up in memory:

```text
Test database: postgres://app:[REDACTED:db_uri_password:5f1e9c02]@db.internal:5432/app
```

- `remember` replies as usual — the agent gets no error;
- in `search`, the agent sees the text with the placeholder;
- the hash is the first 8 characters of the value's SHA-256: it shows whether two records contained the same secret, but the secret cannot be recovered from it;
- the operation log records only which rules fired and how many times — no values, no hashes.

To reduce false positives, values that look like code or identifiers (such as `config.api_key` or a variable name), obvious placeholders in example URLs, and already-scrubbed text are left alone.

Memory Guard is rule-based and recognizes known formats. A secret in an unusual format may slip through. Do not rely on it as your only safeguard: do not ask the agent to "remember the password" — keep secrets in a password manager. If a secret did end up in memory, delete the record with [`forget`](/reference/forget/) and rotate the secret.

## Where else these rules apply

- **mmw-agent on your machine** — the same copy of the rules scrubs session history **before upload**. A test checks that the agent's rules match the server's. See [Session history](/agent/session-history/).
- **The server when receiving session history** — every chunk is scrubbed again.
- **The Telegram bot** — notes are saved through the same `remember`.
- **The archivist** — its reply is scrubbed before it can end up in a `fact_key`.

## Where next
