Skip to content

Memory API reference

Complete reference for Astrocyte’s four core memory operations — retain, recall, reflect, and forget — via Python library and REST gateway.


OperationPurposePython methodHTTP endpoint
retainStore content into memoryastrocyte.retain()POST /v1/retain
recallRetrieve relevant memoriesastrocyte.recall()POST /v1/recall
reflectSynthesize an answer from memoryastrocyte.reflect()POST /v1/reflect
forgetRemove memoriesastrocyte.forget()POST /v1/forget

Ingests content, extracts facts, deduplicates, and stores into a memory bank.

async def retain(
self,
content: str,
bank_id: str,
*,
metadata: dict[str, str | int | float | bool | None] | None = None,
tags: list[str] | None = None,
context: AstrocyteContext | None = None,
content_type: str = "text",
extraction_profile: str | None = None,
occurred_at: datetime | None = None,
source: str | None = None,
pii_detected: bool = False,
) -> RetainResult:
ParameterTypeDescription
contentstrThe text content to store.
bank_idstrTarget memory bank identifier.
metadatadictOptional key-value pairs attached to the memory.
tagslist[str]Optional tags for categorisation and filtering.
contextAstrocyteContextOptional actor identity and session context.
content_typestrContent format hint. Defaults to "text".
extraction_profilestrNamed extraction profile to control fact extraction behaviour.
occurred_atdatetimeTimestamp of when the content originally occurred.
sourcestrFree-text source label (e.g. "slack", "meeting-notes").
pii_detectedboolFlag indicating the content contains PII. Defaults to False.
FieldTypeDescription
storedboolWhether the content was stored.
memory_idstr | NoneID of the created memory, if stored.
deduplicatedboolWhether the content was merged with an existing memory.
errorstr | NoneError message if the operation failed.
retention_actionstr | NoneAction taken by the retention pipeline (e.g. "created", "merged").
curatedboolWhether curation rules were applied.
memory_layerstr | NoneLayer the memory was stored in (e.g. "episodic", "semantic").
from astrocyte import Astrocyte
ast = Astrocyte.from_config("astrocyte.yaml")
result = await ast.retain(
content="Customer prefers dark-mode UI and weekly email digests.",
bank_id="user-prefs",
tags=["ui", "notifications"],
metadata={"customer_id": "cust_8291"},
source="support-ticket",
)
print(result.memory_id) # "mem_3f8a..."
print(result.deduplicated) # False
POST /v1/retain
Content-Type: application/json
Authorization: Bearer <token>
{
"content": "Customer prefers dark-mode UI and weekly email digests.",
"bank_id": "user-prefs",
"metadata": {"customer_id": "cust_8291"},
"tags": ["ui", "notifications"]
}
Terminal window
curl -X POST https://gateway.example.com/v1/retain \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ASTROCYTE_TOKEN" \
-d '{
"content": "Customer prefers dark-mode UI and weekly email digests.",
"bank_id": "user-prefs",
"tags": ["ui", "notifications"],
"metadata": {"customer_id": "cust_8291"}
}'

Searches one or more memory banks and returns ranked hits.

async def recall(
self,
query: str,
bank_id: str | None = None,
*,
banks: list[str] | None = None,
strategy: Literal["cascade", "parallel", "first_match"] | MultiBankStrategy | None = None,
max_results: int = 10,
max_tokens: int | None = None,
tags: list[str] | None = None,
context: AstrocyteContext | None = None,
external_context: list[MemoryHit] | None = None,
fact_types: list[str] | None = None,
time_range: tuple[datetime, datetime] | None = None,
include_sources: bool = False,
layer_weights: dict[str, float] | None = None,
detail_level: str | None = None,
) -> RecallResult:
ParameterTypeDescription
querystrNatural-language search query.
bank_idstrSingle bank to search. Mutually exclusive with banks.
bankslist[str]Multiple banks to search.
strategystr | MultiBankStrategyMulti-bank search strategy: "cascade", "parallel", or "first_match".
max_resultsintMaximum number of hits to return. Defaults to 10.
max_tokensintToken budget for returned content.
tagslist[str]Filter results to memories matching these tags.
contextAstrocyteContextOptional actor identity and session context.
external_contextlist[MemoryHit]Additional context to blend into results.
fact_typeslist[str]Filter to specific fact types (e.g. ["preference", "event"]).
time_rangetuple[datetime, datetime]Restrict results to a time window.
include_sourcesboolInclude source metadata in each hit. Defaults to False.
layer_weightsdict[str, float]Per-layer scoring weights (e.g. {"semantic": 1.2, "episodic": 0.8}).
detail_levelstrControls verbosity of returned text.
FieldTypeDescription
hitslist[MemoryHit]Ranked list of matching memories.
total_availableintTotal matches before max_results truncation.
truncatedboolWhether results were truncated.
traceRecallTrace | NoneDiagnostic trace of the recall pipeline.
authority_contextstr | NoneAuthority resolution context, if applicable.
FieldTypeDescription
memory_idstrUnique memory identifier.
textstrMemory content.
scorefloatRelevance score.
bank_idstrBank the memory belongs to.
metadatadictAttached metadata.
tagslist[str]Tags on the memory.
occurred_atdatetime | NoneWhen the content originally occurred.
sourcestr | NoneSource label.
memory_layerstr | NoneLayer (e.g. "episodic", "semantic").

Single bank:

result = await ast.recall("What UI theme does the customer prefer?", bank_id="user-prefs")
for hit in result.hits:
print(f"[{hit.score:.2f}] {hit.text}")

Multi-bank parallel:

result = await ast.recall(
"deployment issues last week",
banks=["incidents", "runbooks", "team-notes"],
strategy="parallel",
max_results=20,
)

Multi-bank cascade (searches banks in order, stops when enough results are found):

result = await ast.recall(
"API rate limit policy",
banks=["policies", "runbooks", "general"],
strategy="cascade",
)

Tag filtering:

result = await ast.recall(
"onboarding steps",
bank_id="docs",
tags=["onboarding", "getting-started"],
)

Time range filtering:

from datetime import datetime, timedelta
week_ago = datetime.now() - timedelta(days=7)
result = await ast.recall(
"customer complaints",
bank_id="support",
time_range=(week_ago, datetime.now()),
)
Terminal window
curl -X POST https://gateway.example.com/v1/recall \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ASTROCYTE_TOKEN" \
-d '{
"query": "What UI theme does the customer prefer?",
"bank_id": "user-prefs",
"max_results": 5
}'

Multi-bank:

Terminal window
curl -X POST https://gateway.example.com/v1/recall \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ASTROCYTE_TOKEN" \
-d '{
"query": "deployment issues last week",
"banks": ["incidents", "runbooks", "team-notes"],
"strategy": "parallel",
"max_results": 20
}'

reflect() — Synthesize an answer from memory

Section titled “reflect() — Synthesize an answer from memory”

Recalls relevant memories and synthesizes a natural-language answer. Use reflect when you want an interpreted response rather than raw hits.

async def reflect(
self,
query: str,
bank_id: str | None = None,
*,
banks: list[str] | None = None,
strategy: Literal["cascade", "parallel", "first_match"] | MultiBankStrategy | None = None,
max_tokens: int | None = None,
tags: list[str] | None = None,
context: AstrocyteContext | None = None,
include_sources: bool = True,
dispositions: Any | None = None,
) -> ReflectResult:
ParameterTypeDescription
querystrNatural-language question to answer from memory.
bank_idstrSingle bank to search. Mutually exclusive with banks.
bankslist[str]Multiple banks to search.
strategystr | MultiBankStrategyMulti-bank search strategy.
max_tokensintToken budget for the synthesised answer.
tagslist[str]Filter source memories by tag.
contextAstrocyteContextOptional actor identity and session context.
include_sourcesboolReturn the source memories used. Defaults to True.
dispositionsAnyOptional disposition hints for answer style.
FieldTypeDescription
answerstrSynthesised natural-language answer.
confidencefloat | NoneConfidence score between 0 and 1.
sourceslist[MemoryHit] | NoneSource memories the answer was derived from.
observationslist[str] | NoneAdditional observations from the synthesis.
authority_contextstr | NoneAuthority resolution context, if applicable.
result = await ast.reflect(
"What are this customer's communication preferences?",
bank_id="user-prefs",
include_sources=True,
)
print(result.answer)
# "The customer prefers dark-mode UI and weekly email digests."
print(result.confidence)
# 0.92
for src in result.sources:
print(f" - {src.memory_id}: {src.text[:60]}...")
Terminal window
curl -X POST https://gateway.example.com/v1/reflect \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ASTROCYTE_TOKEN" \
-d '{
"query": "What are this customer'\''s communication preferences?",
"bank_id": "user-prefs",
"max_tokens": 200,
"include_sources": true
}'

Deletes or archives memories from a bank. Supports targeted deletion by ID, by tag, by date, or full bank wipe.

async def forget(
self,
bank_id: str,
*,
memory_ids: list[str] | None = None,
tags: list[str] | None = None,
scope: str | None = None,
context: AstrocyteContext | None = None,
compliance: bool = False,
reason: str | None = None,
before_date: datetime | None = None,
) -> ForgetResult:
ParameterTypeDescription
bank_idstrBank to delete from.
memory_idslist[str]Specific memory IDs to delete.
tagslist[str]Delete all memories matching these tags.
scopestrSet to "all" to delete every memory in the bank.
contextAstrocyteContextOptional actor identity and session context.
complianceboolMark as a compliance-driven deletion (logged for audit). Defaults to False.
reasonstrFree-text reason for the deletion (stored in audit log).
before_datedatetimeDelete memories with occurred_at before this date.
FieldTypeDescription
deleted_countintNumber of memories permanently deleted.
archived_countintNumber of memories archived instead of deleted.

Delete specific IDs:

result = await ast.forget(
"user-prefs",
memory_ids=["mem_3f8a", "mem_91cb"],
)
print(result.deleted_count) # 2

Delete by tag:

result = await ast.forget("user-prefs", tags=["deprecated"])

Delete all memories in a bank:

result = await ast.forget("user-prefs", scope="all")

Compliance deletion with reason:

result = await ast.forget(
"user-prefs",
memory_ids=["mem_3f8a"],
compliance=True,
reason="GDPR erasure request #4821",
)

Delete before a date:

from datetime import datetime
result = await ast.forget(
"logs",
before_date=datetime(2025, 1, 1),
reason="Retention policy: remove data older than 1 year",
)
Terminal window
curl -X POST https://gateway.example.com/v1/forget \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ASTROCYTE_TOKEN" \
-d '{
"bank_id": "user-prefs",
"memory_ids": ["mem_3f8a", "mem_91cb"]
}'

Delete by tag:

Terminal window
curl -X POST https://gateway.example.com/v1/forget \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ASTROCYTE_TOKEN" \
-d '{
"bank_id": "user-prefs",
"tags": ["deprecated"]
}'

from astrocyte import Astrocyte
ast = Astrocyte.from_config("astrocyte.yaml")

The YAML file defines storage backends, memory banks, extraction profiles, and gateway settings. See Configuration reference for the full schema.

from astrocyte import Astrocyte, AstrocyteConfig
config = AstrocyteConfig(
storage_backend="postgresql",
connection_url="postgresql://localhost:5432/astrocyte",
)
ast = Astrocyte(config)

All four operations accept an optional context parameter carrying actor identity and session metadata.

from astrocyte import AstrocyteContext, ActorIdentity
ctx = AstrocyteContext(
actor=ActorIdentity(actor_id="user_42", role="admin"),
session_id="sess_abc123",
)
result = await ast.retain(
content="...",
bank_id="notes",
context=ctx,
)

The context is used for access control enforcement and audit logging. When omitted, the operation runs with the default identity configured in astrocyte.yaml.

See Access control setup for role-based and attribute-based access policies.


Astrocyte raises typed exceptions for common failure modes.

ExceptionHTTP statusWhen
AccessDenied403The actor lacks permission for the requested operation or bank.
RateLimited429Too many requests. Retry after the duration in the retry_after field.
BankNotFound404The specified bank_id does not exist.
ValidationError400Invalid parameters (e.g. empty content, unknown bank in list).
from astrocyte.exceptions import AccessDenied, RateLimited
try:
result = await ast.recall("sensitive data", bank_id="restricted")
except AccessDenied as e:
print(f"Permission denied: {e}")
except RateLimited as e:
print(f"Rate limited. Retry after {e.retry_after}s")

Error responses follow a consistent JSON structure:

{
"error": {
"code": "access_denied",
"message": "Actor user_42 lacks read access to bank 'restricted'."
}
}