Skip to main content

Python client for SmartMemory Service API

Project description

SmartMemory Python Client

Official Python client for the SmartMemory Service API.

PyPI version Python 3.11+ License: MIT

Features

  • Type-safe API with Pydantic models
  • Automatic JWT authentication with token handling
  • Full API coverage (CRUD, ingestion, search, links, temporal, etc.)
  • Comprehensive error handling
  • Clean, manually-maintained code (no code generation complexity)
  • Automatic scoping - tenant/workspace/user derived from JWT token

Installation

pip install smartmemory-client

Development Installation

git clone https://github.com/smartmemory/smart-memory-client.git
cd smart-memory-client
pip install -e ".[dev]"

Quick Start

from smartmemory_client import SmartMemoryClient

# Initialize client with authentication
client = SmartMemoryClient(
    base_url="http://localhost:9001",
    api_key="your_jwt_token"  # Or set SMARTMEMORY_API_KEY env var
)

# Add a memory
item_id = client.add("This is a test memory")
print(f"Added memory: {item_id}")

# Search memories
results = client.search("test", top_k=5)
for memory in results:
    print(f"{memory.item_id}: {memory.content}")

# Ingest with full pipeline
result = client.ingest(
    content="Complex content to process",
    extractor_name="llm",
    context={"source": "user", "timestamp": "2025-11-10"}
)
print(f"Ingested: {result['item_id']}")

Authentication

The client requires a JWT token for authentication. You can provide it in two ways:

1. Pass as parameter

client = SmartMemoryClient(
    base_url="http://localhost:9001",
    api_key="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
)

2. Set environment variable

export SMARTMEMORY_API_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
import os
client = SmartMemoryClient(
    base_url="http://localhost:9001",
    api_key=os.getenv("SMARTMEMORY_API_KEY")
)

Getting a JWT Token

SmartMemory uses Clerk for authentication (PLAT-SSO-IDP-1). /auth/signup and /auth/login have been removed. Tokens are obtained via the Clerk-hosted login flow or, for programmatic/service access, via the Clerk session exchange endpoint:

# Exchange a Clerk session token for a SmartMemory JWT + cookies
curl -X POST "http://localhost:9001/auth/clerk/session" \
  -H "Authorization: Bearer <clerk_session_token>"
# Response sets sm_access_token cookie and returns {"access_token": "eyJ..."}

# Verify / inspect the token
curl "http://localhost:9001/auth/me" \
  -H "Authorization: Bearer <sm_access_token>"
# Response: {"id": "...", "email": "...", "default_team_id": "..."}

For local E2E / integration tests, set SM_E2E_TOKEN and SM_E2E_TEAM_ID env vars (captured from a real Clerk login or the sm_access_token cookie) and the test fixtures will inject them automatically.

API Reference

Memory Operations

Add Memory

# Simple add
item_id = client.add("Remember this")

# With metadata
item_id = client.add(
    "Important fact",
    metadata={"source": "user", "priority": "high"},
    use_pipeline=True  # Run full extraction pipeline
)

# Fast add (no pipeline)
item_id = client.add("Quick note", use_pipeline=False)

Search Memories

# Simple search
results = client.search("AI concepts", top_k=10)

# Search with SSG for better multi-hop reasoning
results = client.search("AI concepts", top_k=10, use_ssg=True)

# Search specific memory type
results = client.search("conversation", memory_type="episodic")

# Process results
for memory in results:
    print(f"{memory.item_id}: {memory.content}")
    print(f"Score: {memory.score}")
    print(f"Metadata: {memory.metadata}")

Advanced Search (SSG)

# Best for general queries (query_traversal algorithm)
results = client.search_advanced(
    query="What are neural networks?",
    algorithm="query_traversal",
    max_results=15
)

# Best for high precision (triangulation_fulldim algorithm)
results = client.search_advanced(
    query="Specific technical fact",
    algorithm="triangulation_fulldim",
    max_results=10
)

# Process results
for memory in results:
    print(f"{memory.item_id}: {memory.content}")

SSG Benefits:

  • ✅ Superior multi-hop reasoning across related memories
  • ✅ Better contextual retrieval (0.91 precision/recall vs 0.88)
  • ✅ Higher faithfulness (facts vs opinions)
  • ✅ Improved conversation and knowledge graph traversal

Based on: Eric Lester. (2025). Novel Semantic Similarity Graph Traversal Algorithms for Semantic Retrieval Augmented Generation Systems.

Get Memory

memory = client.get("item_123")
if memory:
    print(f"Content: {memory.content}")
    print(f"Type: {memory.memory_type}")
    print(f"Metadata: {memory.metadata}")

Update Memory

# Update content
client.update("item_123", content="Updated content")

# Update metadata
client.update("item_123", metadata={"updated": True})

# Update both
client.update("item_123", content="New content", metadata={"version": 2})

Delete Memory

if client.delete("item_123"):
    print("Memory deleted")

Ingestion

# Ingest with full pipeline
# Note: user_id, tenant_id, workspace_id are automatically derived from JWT token
result = client.ingest(
    content="User: Hello\nAssistant: Hi there!",
    extractor_name="llm",
    context={
        "conversation_id": "123",
        "timestamp": "2025-11-10",
        "source": "chat_interface"
    }
)

print(f"Ingested: {result['item_id']}")
print(f"Queued for processing: {result['queued']}")

Links and Relationships

# Create link between memories
client.link("concept_1", "concept_2", link_type="RELATED")
client.link("cause_id", "effect_id", link_type="CAUSES")

# Get neighbors
neighbors = client.get_neighbors("item_123")
for neighbor in neighbors:
    print(f"{neighbor['id']}: {neighbor['relation']}")

Code Search

# Semantic search over indexed code entities
results = client.code_search("authentication functions", semantic=True)
for entity in results:
    print(f"{entity['name']} ({entity['entity_type']}) — {entity['file_path']}:{entity['line_number']}")
    print(f"  Score: {entity['score']}")

# Filter by entity type and repo
results = client.code_search(
    "payment handler",
    semantic=True,
    entity_type="function",
    repo="my-service"
)

# Non-semantic (Cypher substring match, default)
results = client.code_search("authenticate")

Enrichment

# Enrich a memory
result = client.enrich("item_123", routines=["sentiment", "keywords"])
print(f"Enrichment result: {result}")

Personalization

# Update user preferences
result = client.personalize(
    traits={"learning_style": "visual"},
    preferences={"language": "en", "complexity": "advanced"}
)

Feedback

# Reinforce recalled memory items: bumps retention_score immediately and
# strengthens CO_RETRIEVED edges between items (feeding the Hebbian evolver).
results = client.search("what did we decide about auth?")
result = client.feedback(
    item_ids=[r.item_id for r in results],
    outcome="helpful",  # "helpful" | "misleading" | "neutral"
    query="what did we decide about auth?",
)
# result == {"updated": N, "edges_strengthened": M, "outcome": "helpful"}

Reasoning Traces (System 2 Memory)

# Extract reasoning from content
result = client.extract_reasoning('''
    Thought: I need to analyze this bug.
    Action: Let me search for the function.
    Observation: Found the issue in line 42.
    Conclusion: The fix is to add a null check.
''')
if result['has_reasoning']:
    print(f"Found {result['step_count']} reasoning steps")

# Store a reasoning trace
result = client.store_reasoning_trace(
    trace={
        "trace_id": "trace_123",
        "steps": [
            {"type": "thought", "content": "Analyzing the problem"},
            {"type": "conclusion", "content": "Found the solution"},
        ],
        "task_context": {"goal": "Fix bug", "domain": "python"},
    },
    artifact_ids=["code_fix_456"]  # Link to resulting artifacts
)

# Query reasoning traces ("why" queries)
result = client.query_reasoning("why did I use async/await?")
for trace in result['traces']:
    print(f"Trace {trace['trace_id']}: {trace['content'][:100]}...")

# Get specific reasoning trace
trace = client.get_reasoning_trace("trace_123")

Synthesis Evolution (Opinions & Observations)

# Form opinions from episodic patterns
result = client.synthesize_opinions()
print(f"Status: {result['status']}")

# Create entity summaries from scattered facts
result = client.synthesize_observations()
print(f"Status: {result['status']}")

# Update opinion confidence based on new evidence
result = client.reinforce_opinions()
print(f"Status: {result['status']}")

Health Check

# Check service health
health = client.health_check()
print(health)  # {'status': 'healthy'}

Summary Statistics

# Get memory statistics
summary = client.get_summary()
print(f"Total memories: {summary.get('total_count', 0)}")

Usage in Projects

Maya Integration

# maya/requirements.txt
smartmemory-client>=1.0.0

# maya/maya/api/memory_manager.py
import os
from smartmemory_client import SmartMemoryClient

class MemoryManager:
    def __init__(self, smartmemory_url):
        self.client = SmartMemoryClient(
            base_url=smartmemory_url,
            api_key=os.getenv("SMARTMEMORY_API_KEY")
        )
    
    def ingest_conversation(self, content, metadata):
        # user_id, tenant_id, workspace_id automatically from JWT token
        return self.client.ingest(
            content=content,
            extractor_name="llm",
            context=metadata
        )
    
    def retrieve_relevant_memories(self, query):
        return self.client.search(query=query, top_k=5)

Studio Integration

import os
from smartmemory_client import SmartMemoryClient

client = SmartMemoryClient(
    base_url=os.getenv("SMARTMEMORY_URL"),
    api_key=os.getenv("SMARTMEMORY_API_KEY")
)

# Use client for memory operations
memories = client.search("project requirements", top_k=10)

Error Handling

from smartmemory_client import SmartMemoryClient, SmartMemoryClientError

client = SmartMemoryClient("http://localhost:9001", api_key="token")

try:
    item_id = client.add("Test memory")
except SmartMemoryClientError as e:
    print(f"Error: {e}")

Configuration

Environment Variables

  • SMARTMEMORY_API_KEY - JWT token for authentication
  • SMARTMEMORY_URL - Base URL of the SmartMemory service (optional)

Client Options

client = SmartMemoryClient(
    base_url="http://localhost:9001",
    api_key="your_jwt_token",
    timeout=30.0,           # Request timeout in seconds
    verify_ssl=True         # Verify SSL certificates
)

Development

Setup

git clone https://github.com/smartmemory/smart-memory-client.git
cd smart-memory-client
pip install -e ".[dev]"

Running Tests

# Run all tests
pytest

# Run with coverage
pytest --cov=smartmemory_client --cov-report=html

# Run specific test
pytest tests/test_client.py::test_add_memory

Code Quality

# Format code
black smartmemory_client tests

# Sort imports
isort smartmemory_client tests

# Lint
ruff check smartmemory_client tests

# Type check
mypy smartmemory_client

Versioning

This package follows Semantic Versioning:

  • Major (1.0.0 → 2.0.0): Breaking changes
  • Minor (1.0.0 → 1.1.0): New features, backward compatible
  • Patch (1.0.0 → 1.0.1): Bug fixes

The client version is synced with the SmartMemory Service version.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Reporting Issues

Please report issues on GitHub Issues.

License

MIT License - see LICENSE file for details.

Links

Changelog

See CHANGELOG.md for version history.


Made with ❤️ by the SmartMemory Team

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

smartmemory_client-0.6.0.tar.gz (59.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

smartmemory_client-0.6.0-py3-none-any.whl (35.8 kB view details)

Uploaded Python 3

File details

Details for the file smartmemory_client-0.6.0.tar.gz.

File metadata

  • Download URL: smartmemory_client-0.6.0.tar.gz
  • Upload date:
  • Size: 59.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for smartmemory_client-0.6.0.tar.gz
Algorithm Hash digest
SHA256 a2a76870354ad4872fbd6f26ef369ab218082c12baded27b4c3015bb47aa7926
MD5 9df84298b57b7dfc40ee952bba1894c7
BLAKE2b-256 ef9d38ac1f09b1a10da615c473865cf69ba26bb3263c8217d92654d25f29c94d

See more details on using hashes here.

File details

Details for the file smartmemory_client-0.6.0-py3-none-any.whl.

File metadata

File hashes

Hashes for smartmemory_client-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 74ec68f54dcf0dc27840b36cf9e3d603e1c2314561eef9701bacc0ada32e0ee9
MD5 33c70e7d40bdcd53158ee0c28b2c8c6f
BLAKE2b-256 07b6ffd9943797e753cd20b4b599c9d074475a0d5927217d4c61545820c8c5cd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page