Docs⌘ K  Search
Docs/Memory/Memories
Memory API

Memories

Store, retrieve, update, and delete memories. Memories are the core building blocks of Hebbrix - they store knowledge that your AI can recall later.

app.hebbrix.com/memories/mem_01HM2K
Memory · mem_01HM2K9F4ALong-term
User prefers dark mode and writes Python. Works on project Atlas, a multi-tenant analytics platform. Asked twice about staging deploys this month.
Useralex@acme.com
CollectionProduct docs
CreatedJun 12, 2026
Sourcechat completion
Reinforced4 times
Tierworking → long-term
Extracted entities
Pythondark modeAtlasstaging deploy
One memory, fully resolved. Tier, provenance, reinforcement count, and the entities the graph pulled out, all on one screen.

01. Overview

A memory is a piece of information that you want your AI to remember. This could be:

  • User preferences ("User prefers dark mode")
  • Facts from conversations ("User's birthday is January 15th")
  • Knowledge from documents ("The API rate limit is 100 requests per minute")
  • Any structured or unstructured data you want to store

02. Choose an ingestion path

Choose explicit raw storage when you need to preserve source text, or fact extraction when you need atomic, updatable facts. Neither is universally better for retrieval. The smart /v1/memoriesendpoint defaults to asynchronous extraction; /v1/memories/rawexplicitly skips extraction. Storage, indexing and account quotas still apply.

SurfacePurposeReadiness contract
POST /v1/memoriesGeneral smart write with infer: true; infer: false stores source text.Queued extraction by default. Follow the returned poll_url; do not assume a 202 is searchable.
POST /v1/memories/processExplicit conversation extraction and revision events.Queued by default; async_dispatch: false waits for inline processing. Inspect indexing status separately.
POST /v1/memories/rawStore already-authored facts without inference.Returns an ID; indexing may still be pending. Exact duplicates reuse that ID rather than create a second row.
POST /v1/fast/ingestLow-overhead direct ingestion, not smart revision.Use its indexing receipt; an accepted write is not a completed search barrier.
POST /v1/chat/completionsOptional drop-in retrieval and post-response learning.Learning is consented, queued work. Poll its learning job before a dependent session read.

Carry the same collection_id and user_id through writing, search, profile and chat. Poll the returned job with the same owner credentials. Session IDs are conversation provenance, not an end-user isolation boundary. The public OpenAPI is the full customer API, including account management; this table is the focused memory integration path.

/memories/raw/memories/process
What it doesStores your text verbatim, then indexes it (with automatic context-window chunking) in the background. No LLM.Runs an LLM to extract clean atomic facts, resolve references, and supersede outdated info.
Retrieval recallPreserves original wording, including irrelevant or outdated statements.Normalizes facts and resolves corrections, but may omit or paraphrase source text. Evaluate recall on your workload.
Write latencyNo extraction call; indexing readiness is separate.Queued acknowledgement by default; completion depends on models, indexing and worker load. No three-second guarantee.
LLM costNonePer-memory LLM call
Supersession / dedupExact content deduplication, not semantic revision. Different old and corrected facts remain separate.Yes. Corrections replace old facts; redundant facts are merged

Use explicit /raw storage for

  • Chat history & agent memory
  • Documents, notes, transcripts
  • Fact stores & knowledge bases
  • Bulk import & high-throughput writes
  • Anywhere recall and speed matter most

Use /process when you need

  • "Latest value wins" (users correct/update facts over time)
  • Conflict resolution between contradictory facts
  • Deduplicated, normalized atomic facts
  • A curated knowledge base with explicit revision history

Revision review compares the original message with current facts in the same owner scope. A replacement must identify the same subject and an assertion that has changed; adding another job, car or relative does not by itself retire an existing one. Reviewed edits bind the exact predecessor and replacement and preserve unaffected clauses. Semantic review is fallible: inspect UPDATE events and their predecessor IDs rather than assuming every submitted correction was applied. Session and run IDs record provenance, not new owners.

Readiness is separate from acceptance: a queued extraction or indexing operation is not proof that a fact is searchable. Poll the returned job, or use the direct-write indexing receipt described below.

03. Endpoints

04. Response shape (POST /v1/memories)

By default, POST /v1/memories returns HTTP 202 withjob_id, status and poll_url. This accepts an extraction job; it does not return an inlineresults array. Poll the returned URL with the same credentials until the job completes or fails.

Default asynchronous response
POST /v1/memories  →  HTTP 202
{
  "job_id": "job_example",
  "status": "queued",
  "poll_url": "/v1/memory-jobs/job_example"
}

For direct storage, send infer: false andwait_for_index: true. This skips fact extraction and returns an inline HTTP 200 result. Inspect searchable andindex_wait_status; do not assume a bounded indexing wait succeeded. For inline extraction instead, use /v1/memories/process withasync_dispatch: false.

  • collection_id: the resolved collection the memories were stored in.
  • processing_status "async": the memory row is persisted and indexed in the background. Poll GET /v1/memories/{id} (or use Background Jobs) until it is searchable.
  • created_count, updated_count, skipped_count: a summary derived from the per-row events (ADD / UPDATE / NOOP).
Memory IDs: each results[].id is the PARENT Memory.id, retrievable via GET /v1/memories/{id}. The proposition-style ids you may see in search results (like uuid::subj=...) are a search-layer artifact and are NOT returned by POST /v1/memories.
Direct-write response (not the default extraction response)
POST /v1/memories (infer: false, wait_for_index: true) → HTTP 200
{
  "results": [
    { "id": "mem_abc123", "event": "ADD", "memory": "User prefers dark mode" }
  ],
  "collection_id": "col_default",
  "processing_status": "async",
  "created_count": 1,
  "updated_count": 0,
  "skipped_count": 0
}

05. Destructive operations: dry-run & confirmation

Bulk deletes that wipe everything support two opt-in safety controls so you can preview the blast radius before committing. Both are backward compatible.

  • DELETE /v1/memories/all?dry_run=true returns {"deleted_count":0,"dry_run":true,"would_delete":N} and deletes NOTHING. Use it to preview how many memories would be removed.
  • An optional header X-Hebbrix-Confirm-Destructive: all-memories guards the real delete. If the header is PRESENT it must equal all-memories or the request is rejected with HTTP 400. If OMITTED, behavior is unchanged.
  • The same pattern applies to DELETE /v1/collections/all, whose confirm value is all-collections.
Python
import requests

BASE = "https://api.hebbrix.com/v1"
H = {"Authorization": "Bearer <your-api-key>"}

# 1) Dry-run first: preview the blast radius, deletes NOTHING
preview = requests.delete(
    f"{BASE}/memories/all",
    headers=H,
    params={"dry_run": "true"},
).json()
# {"deleted_count": 0, "dry_run": True, "would_delete": 1287}
print(f"Would delete {preview['would_delete']} memories")

# 2) Confirmed delete: header must equal "all-memories" if present
result = requests.delete(
    f"{BASE}/memories/all",
    headers={**H, "X-Hebbrix-Confirm-Destructive": "all-memories"},
).json()
print(f"Deleted {result['deleted_count']} memories")

# Same safety pattern for collections (confirm value "all-collections")
requests.delete(
    f"{BASE}/collections/all",
    headers={**H, "X-Hebbrix-Confirm-Destructive": "all-collections"},
)

06. Code Examples

Create a Memory

Python
import asyncio
from hebbrix import MemoryClient

async def main():
    async with MemoryClient(api_key="mem_sk_...") as client:
        collection = await client.collections.create(name="my-agent")

        # Simple memory (SDK calls the smart-extract POST /v1/memories endpoint)
        memory = await client.memories.create(
            collection_id=collection["id"],
            content="User's favorite color is blue",
        )

        # Memory with importance + metadata (tags live inside metadata)
        await client.memories.create(
            collection_id=collection["id"],
            content="User completed Python certification on 2024-01-15",
            importance=0.8,
            metadata={
                "tags": ["education", "python"],
                "certification_provider": "Coursera",
                "completion_date": "2024-01-15",
            },
        )

asyncio.run(main())

Process Conversations (fact extraction)

Python
import os
import requests

BASE = "https://api.hebbrix.com/v1"
H = {"Authorization": f"Bearer {os.environ['HEBBRIX_API_KEY']}"}

# POST /v1/memories/process: hand it a chat transcript; the backend
# extracts atomic facts, detects conflicts, and emits ADD/UPDATE/NOOP
# events for each resulting memory. Explicit false requests inline results;
# omit it for the default 202 job receipt and poll the returned poll_url.
r = requests.post(
    f"{BASE}/memories/process",
    headers=H,
    json={
        "async_dispatch": False,
        "messages": [
            {"role": "user", "content": "Hi! My name is Alex and I work at Acme Corp."},
            {"role": "assistant", "content": "Nice to meet you, Alex!"},
        ]
    },
)
result = r.json()

print(f"Facts extracted: {result['facts_extracted']}")
print(f"Created: {result['memories_created']}")
print(f"Updated: {result['memories_updated']}")

# Later, user corrects their name: the old memory is updated
r = requests.post(
    f"{BASE}/memories/process",
    headers=H,
    json={
        "async_dispatch": False,
        "messages": [
            {"role": "user", "content": "Actually, my name is Jordan, not Alex."},
            {"role": "assistant", "content": "No problem, Jordan!"},
        ]
    },
)
result = r.json()
# result["events"][0]["event"] == "UPDATE"
# result["events"][0]["previous_content"] == "Alex is the user's name"

Batch Create

Python
import os
import requests

BASE = "https://api.hebbrix.com/v1"
H = {"Authorization": f"Bearer {os.environ['HEBBRIX_API_KEY']}"}

# POST /v1/memories/batch: create multiple memories in one request (max 100).
# Note: collection_id is top-level, NOT per-memory.
memories = [
    {"content": "User prefers email over phone calls"},
    {"content": "User works in software development"},
    {"content": "User is based in EST timezone"},
]

r = requests.post(
    f"{BASE}/memories/batch",
    headers=H,
    json={
        "memories": memories,
        "collection_id": "col_default",
    },
)
result = r.json()
print(f"Created {result['created']} memories")

List and Filter (SDK)

Python SDK
import asyncio
import os
from hebbrix import MemoryClient

async def main():
    async with MemoryClient(api_key=os.environ["HEBBRIX_API_KEY"]) as client:
        # --- Explicit page-at-a-time access ---
        page = await client.memories.list_page(limit=50)
        # page = {"items": [...], "next_cursor": str | None,
        #         "has_more": bool, "total_count": int}
        print(f"Showing {len(page['items'])} of {page['total_count']} memories")

        # Fetch the next page if there is one
        if page["has_more"]:
            next_page = await client.memories.list_page(
                cursor=page["next_cursor"], limit=50
            )
            print(f"Next page has {len(next_page['items'])} memories")

        # Filter by collection
        page = await client.memories.list_page(
            collection_id="col_customer_support", limit=20
        )

        # --- Simple "give me everything" iteration ---
        # iter_all follows next_cursor until has_more == False
        async for memory in client.memories.iter_all(collection_id="col_customer_support"):
            print(memory["id"], memory["content"][:80])

asyncio.run(main())

List and Filter (raw HTTP)

Python (raw HTTP)
import os
import requests

BASE = "https://api.hebbrix.com/v1"
H = {"Authorization": f"Bearer {os.environ['HEBBRIX_API_KEY']}"}

# List all memories (cursor-paginated response)
r = requests.get(f"{BASE}/memories", headers=H, params={"limit": 50})
page = r.json()  # {"items": [...], "next_cursor": ..., "has_more": ..., "total_count": ...}

# Paginate through all
cursor = None
while True:
    params = {"limit": 100}
    if cursor:
        params["cursor"] = cursor
    page = requests.get(f"{BASE}/memories", headers=H, params=params).json()
    for memory in page["items"]:
        process(memory)
    if not page.get("has_more") or not page.get("next_cursor"):
        break
    cursor = page["next_cursor"]

07. cURL Examples

POST/v1/memories
curl -X POST "https://api.hebbrix.com/v1/memories" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "content": "User prefers dark mode",
  "tags": [
    "preferences"
  ]
}'
GET/v1/memories?limit=10
curl -X GET "https://api.hebbrix.com/v1/memories?limit=10" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"
DELETE/v1/memories/mem_abc123
curl -X DELETE "https://api.hebbrix.com/v1/memories/mem_abc123" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"
POST/v1/memories/process
curl -X POST "https://api.hebbrix.com/v1/memories/process" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "async_dispatch": false,
  "messages": [
    {
      "role": "user",
      "content": "My name is Jordan and I work at Acme Corp."
    },
    {
      "role": "assistant",
      "content": "Nice to meet you, Jordan!"
    }
  ]
}'
POST/v1/memories/bulk-delete
curl -X POST "https://api.hebbrix.com/v1/memories/bulk-delete" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "ids": [
    "mem_abc123",
    "mem_def456"
  ]
}'
DELETE/v1/memories/all
curl -X DELETE "https://api.hebbrix.com/v1/memories/all" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

08. Memory Lifecycle

When you create a memory, Hebbrix automatically:

  1. Embeds the Content. Converts text to vector embeddings for semantic search.
  2. Calculates Importance. Analyzes content to determine relevance and priority.
  3. Extracts Entities. Identifies people, places, concepts and adds to knowledge graph.
  4. Indexes for Search. Adds to BM25 index for keyword matching alongside vectors.
  5. Detects Conflicts. When using /process, checks for conflicting memories and automatically updates or removes outdated information.
Full pipeline propagation: When a memory is updated or deleted, all storage layers are re-indexed: embeddings, vectors, BM25, knowledge graph, propositions, and tiers are all kept in sync automatically.
Ask the docs
reading · this page

Hi! I'm the Hebbrix docs assistant. Ask me anything about this page: setup, code examples, endpoints, pricing, or integrations.