> ## Documentation Index
> Fetch the complete documentation index at: https://docs.memoryo.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Quality Gate

> How MemoryOS blocks noisy, duplicate, rate-limited, or over-budget write traffic before extraction.

The quality gate runs before extraction. It decides whether an `add()` request should be queued at all.

If a request is blocked, MemoryOS still returns HTTP `200`. Check the response body: `status` and `blocked_reason` explain what happened.

## Gate layers

| Layer | What it checks        | Block reason          | Typical action                        |
| ----- | --------------------- | --------------------- | ------------------------------------- |
| `L1`  | Per-user request rate | `rate_limit_exceeded` | Retry after `retry_after_seconds`     |
| `L2`  | Content quality       | `low_quality`         | Send richer conversation context      |
| `L3`  | Semantic duplicate    | `duplicate_query`     | Avoid resending near-identical writes |
| `L4`  | Tenant budget policy  | `budget_exhausted`    | Upgrade or wait for quota reset       |

## Example blocked response

```json theme={null}
{
  "job_id": null,
  "status": "L2",
  "blocked_reason": "low_quality",
  "retry_after_seconds": null,
  "budget_remaining_pct": 0.9134,
  "request_id": "11111111-2222-3333-4444-555555555555",
  "timestamp": "2026-04-17T09:30:00Z"
}
```

## What is not a gate block

A request can pass the quality gate and still produce no permanent memory.

That is handled by the extraction quality loop:

| Post-gate outcome                           | Meaning                                   |
| ------------------------------------------- | ----------------------------------------- |
| `memories_created > 0`                      | Durable memory was stored                 |
| `pending_candidates_buffered > 0`           | Weak signal was buffered, not stored yet  |
| `nothing_to_extract = true` or zero created | Valid conversation, but no durable memory |

For example, this should usually pass the gate but not become a memory:

```text theme={null}
Keep going with the current debugging flow and do not change anything else.
```

It is temporary session context, not long-term user memory.

## How to keep block rates low

* Send coherent conversation turns, not single-word fragments.
* Do not send the same fact repeatedly on every turn.
* Use `Idempotency-Key` for application retries.
* Watch `blocked_reason`, `budget_remaining_pct`, and `processing_status` on `add()` responses.
* Check job status when you need to know whether extraction stored, buffered, or ignored a signal.

## Dashboard visibility

Tenant Dashboard -> Quality Log shows gate blocks and extraction quality signals in one place:

* block layer counts
* pending weak signals
* reinforced signals
* retrieval feedback events
* correction jobs

## Related pages

* [Extraction Quality Loop](/concepts/extraction-quality)
* [POST /v1/memories/add](/api-reference/add)
* [Memory Lifecycle and Versioning](/concepts/memory-lifecycle)
