Python client for Memtrace — LLM-agnostic memory layer for AI agents.
pip install memtrace-sdkfrom memtrace import Memtrace
client = Memtrace("http://localhost:9100", "mtk_your_api_key")
# Store a memory
client.remember("agent_1", "User prefers dark mode")
# Recall recent memories
memories = client.recall("agent_1", since="24h")
for m in memories.memories:
print(f"[{m.time}] {m.content}")
# Log a decision
client.decide("agent_1", "Use PostgreSQL", "Better JSON support for metadata")from memtrace import AsyncMemtrace
async with AsyncMemtrace("http://localhost:9100", "mtk_your_api_key") as client:
await client.remember("agent_1", "User prefers dark mode")
memories = await client.recall("agent_1")from memtrace import Memtrace, AddMemoryRequest, ListOptions, SearchQuery
client = Memtrace("http://localhost:9100", "mtk_...")
# Add a single memory with full control
mem = client.add_memory(AddMemoryRequest(
agent_id="agent_1",
session_id="sess_1",
memory_type="episodic",
event_type="observation",
content="User clicked the settings button",
tags=["ui", "navigation"],
importance=0.7,
))
# Add multiple memories in a batch
memories = client.add_memories([
AddMemoryRequest(agent_id="agent_1", memory_type="episodic", event_type="general", content="First"),
AddMemoryRequest(agent_id="agent_1", memory_type="episodic", event_type="general", content="Second"),
])
# List with filters
result = client.list_memories(ListOptions(
agent_id="agent_1",
memory_type="decision",
since="7d",
limit=50,
order="desc",
))
# Search with structured query
result = client.search_memories(SearchQuery(
agent_id="agent_1",
memory_types=["episodic", "decision"],
content_contains="dark mode",
min_importance=0.5,
))from memtrace import Memtrace, RegisterAgentRequest
client = Memtrace("http://localhost:9100", "mtk_...")
# Register an agent
agent = client.register_agent(RegisterAgentRequest(
name="my-agent",
description="Handles customer support",
config={"model": "gpt-4"},
))
# List all agents in the org
agents = client.list_agents()
# Get agent details
agent = client.get_agent("agent_1")
# Get agent memory stats
stats = client.get_agent_stats("agent_1")
print(f"Total memories: {stats.memory_count}")
print(f"Active sessions: {stats.active_sessions}")
# Get recent memories for an agent
memories = client.get_agent_memories("agent_1", ListOptions(limit=20, since="24h"))
# Delete an agent (returns None; 404 raises NotFoundError)
client.delete_agent("agent_1")from memtrace import Memtrace, CreateSessionRequest, ContextOptions
client = Memtrace("http://localhost:9100", "mtk_...")
# Create a session
session = client.create_session(CreateSessionRequest(
agent_id="agent_1",
metadata={"task": "onboarding"},
))
# Get LLM-formatted context
ctx = client.get_session_context(session.id, ContextOptions(
since="2h",
include_types=["episodic", "decision"],
max_tokens=4000,
))
print(ctx.context) # Markdown-formatted for LLM consumption
# List sessions (optionally filtered by agent)
all_sessions = client.list_sessions()
for_agent = client.list_sessions(agent_id="agent_1")
# Get memories for a session
session_memories = client.get_session_memories(session.id)
# Close the session
client.close_session(session.id)A Memtrace client points at exactly two things: the deployment URL and an API key.
from memtrace import Memtrace
client = Memtrace(
base_url="https://memtrace.example.com", # one per Memtrace deployment
api_key="mtk_..." # one per organization
)
client.remember(agent_id="my_agent", content="...")The client never names an organization or an Arc instance. The API key carries the org identity opaquely — Memtrace resolves it server-side and routes the request to that org's Arc instance, with that org's database and that org's API key. Operators provision orgs on the server with the memtrace org and memtrace key admin CLI; clients only see the resulting mtk_... string.
This is the same shape as Stripe, OpenAI, AWS — the API key is the tenant credential.
A single backend that needs to write on behalf of multiple Memtrace organizations holds one client per org keyed by API key:
class TenantClients:
def __init__(self):
self._clients: dict[str, Memtrace] = {}
def for_org(self, org_id: str) -> Memtrace:
if org_id not in self._clients:
api_key = secrets.get(f"memtrace_key_{org_id}")
self._clients[org_id] = Memtrace("https://memtrace.example.com", api_key)
return self._clients[org_id]
tenants.for_org("org_acme").remember(agent_id="...", content="...")
tenants.for_org("org_voya").remember(agent_id="...", content="...")If a key is bound to an org that has no Arc instance configured yet, requests raise NoArcInstanceError (see Error Handling below) — operators fix this with memtrace org add-arc.
from memtrace import (
Memtrace,
MemtraceError,
AuthenticationError,
NotFoundError,
ConflictError,
NoArcInstanceError,
)
client = Memtrace("http://localhost:9100", "mtk_...")
try:
agent = client.get_agent("nonexistent")
except NotFoundError:
print("Agent not found")
except AuthenticationError:
print("Invalid API key")
except ConflictError:
print("Duplicate resource")
except NoArcInstanceError:
# The caller's org has no Arc instance configured. An admin must run
# `memtrace org add-arc <org_id>`. Until then, every read/write returns 503.
print("Memtrace is not provisioned for this org yet")
except MemtraceError as e:
print(f"API error ({e.status_code}): {e.message}")cd sdks/python
pip install -e ".[dev]"
pytest -v
ruff check src/ tests/MIT