AsyncMemLayerClient is a drop-in async version of MemLayerClient. Every method is a coroutine — just add await. Use it in FastAPI route handlers, LangGraph nodes, and any other asyncio-based application where blocking I/O would degrade performance or correctness.
Installation
Both clients ship in the same package:
from memlayer import AsyncMemLayerClient
Basic Usage
The recommended pattern is async with — it handles client lifecycle automatically:
import asyncio
from memlayer import AsyncMemLayerClient
async def main():
async with AsyncMemLayerClient(api_key="ml_live_xxx") as client:
# Store a memory
result = await client.remember(
"User prefers dark mode",
user_id="user_123",
agent_id="support_bot",
memory_type="semantic",
importance=0.7,
)
print(result.id)
# Search memories
memories = await client.recall(
"UI preferences",
user_id="user_123",
agent_id="support_bot",
top_k=5,
)
for m in memories:
print(f"[{m.score:.3f}] {m.content}")
asyncio.run(main())
All Methods Are Async
Every method on AsyncMemLayerClient is awaitable. The signatures are identical to the sync client:
| Method | Description |
|---|
await client.remember(content, user_id, agent_id, ...) | Store a memory |
await client.recall(query, user_id, agent_id, ...) | Semantic search |
await client.context(user_id, agent_id, ...) | Load session context |
await client.update(memory_id, user_id, agent_id, new_content, ...) | Update memory content |
await client.forget(memory_id, user_id, agent_id) | Delete one memory |
await client.list(user_id, agent_id, limit, offset) | Browse all stored memories |
await client.forget_all(user_id, agent_id) | Wipe all memories for a user |
await client.is_duplicate(content, user_id, agent_id, ...) | Check before storing |
Return types are identical to the sync client: StoreResult, list[Memory], ContextResult, Memory, ListResult, DeleteResult, and bool respectively.
FastAPI Example
Here is a FastAPI route that loads a user’s context and stores a new memory in a single request:
import os
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from memlayer import AsyncMemLayerClient, MemLayerError
app = FastAPI()
client = AsyncMemLayerClient(api_key=os.environ["MEMLAYER_API_KEY"])
class ChatRequest(BaseModel):
user_id: str
message: str
class ChatResponse(BaseModel):
context_count: int
memory_id: str
@app.post("/chat", response_model=ChatResponse)
async def chat(req: ChatRequest):
try:
# Load relevant context for this user
ctx = await client.context(
user_id=req.user_id,
agent_id="chat_bot",
top_k=10,
current_message=req.message,
)
# Store the incoming message as an episodic memory
result = await client.remember(
content=req.message,
user_id=req.user_id,
agent_id="chat_bot",
memory_type="episodic",
)
return ChatResponse(
context_count=len(ctx.memories),
memory_id=result.id,
)
except MemLayerError as e:
raise HTTPException(status_code=e.status_code, detail=e.detail)
Initialise AsyncMemLayerClient once at module level (outside any route function) and share it across requests. Each method call manages its own httpx.AsyncClient internally, so there is no connection leaking between requests.
Context Manager
async with (recommended)
Manual close
async with AsyncMemLayerClient(api_key="ml_live_xxx") as client:
result = await client.remember(
"something important",
user_id="u1",
agent_id="bot",
)
# Client is cleaned up automatically
client = AsyncMemLayerClient(api_key="ml_live_xxx")
try:
result = await client.remember(
"something important",
user_id="u1",
agent_id="bot",
)
finally:
# No explicit close needed — each call manages its own connection
pass
AsyncMemLayerClient creates a new httpx.AsyncClient for each method call and closes it immediately after — so manual .close() is not required. The async with pattern is still recommended for consistency with connection-pooled clients.
Sync vs Async — When to Use Each
| MemLayerClient (sync) | AsyncMemLayerClient (async) |
|---|
| Best for | Scripts, notebooks, CLI tools | FastAPI, LangGraph, asyncio apps |
| Import | from memlayer import MemLayerClient | from memlayer import AsyncMemLayerClient |
| Usage | client.remember(...) | await client.remember(...) |
| Context manager | with MemLayerClient(...) as client: | async with AsyncMemLayerClient(...) as client: |
| Blocks event loop? | Yes — fine for sync code | No — safe in async contexts |
| Required for LangGraph? | No | ✅ Yes |
Choose AsyncMemLayerClient any time your application already uses async def functions. Mixing the sync client into an async application will block the event loop on each call.