Skip to main content

Vity Python SDK

Long-term memory for AI applications, by Maximem AI.

Store facts and preferences, capture conversations, and recall the right context for every prompt, with a small, typed client for both synchronous and asyncio code.

from maximem_vity import VityClient

client = VityClient(channel="my-app")  # reads MAXIMEM_API_KEY

client.store("User prefers dark mode", memory_type="preference")
print(client.recall("What theme does the user like?"))

Using JavaScript or TypeScript? Install @maximem/vity-sdk from npm.

Contents

Installation

pip install maximem-vity-sdk

Requires Python 3.9 or later. The package is fully typed.

Quick start

Create an API key at app.maximem.ai/api-keys and export it:

export MAXIMEM_API_KEY="mx_..."

A typical agent turn recalls memory before answering and captures the exchange afterwards:

from maximem_vity import VityClient

with VityClient(channel="support-bot") as client:
    # Before answering: fetch relevant memory for the system prompt.
    context = client.recall("Can you book my usual table?")

    # After answering: capture the exchange so Vity can learn from it.
    client.capture(
        [
            {"role": "user", "content": "Can you book my usual table?"},
            {"role": "assistant", "content": "Booked the window table for 7pm."},
        ],
        session_key="conversation-8f2c",
    )

    # Store an explicit fact.
    client.store("Prefers window seats", memory_type="preference", importance="high")

    # Search memory directly.
    for hit in client.search("seating preferences", top_k=5):
        print(f"{hit['score']:.2f}  {hit['content']}")

Async

AsyncVityClient takes the same arguments and exposes the same methods as coroutines:

import asyncio
from maximem_vity import AsyncVityClient

async def main() -> None:
    async with AsyncVityClient(channel="support-bot") as client:
        context = await client.recall("What does the user like to eat?")

asyncio.run(main())

Concepts

Memory belongs to your account. All API keys on a Maximem account share the same memory. Rotating or adding keys never loses anything.

Channels and sessions. Set channel to the name of your integration ("slack", "support-bot"). Pass a session_key to capture() that stays the same for every turn of one conversation and changes for each new conversation.

store() or capture()?

store() capture()
Input One explicit fact A conversation (up to 50 messages)
Saved Immediately In the background, usually within seconds to minutes
What is kept Exactly what you send Durable facts only; small talk is ignored

A successful capture() means the conversation was accepted for processing.

recall() or search()? recall() returns a text block ready to drop into a prompt. search() returns scored memory records for your own logic.

Configuration

Argument Environment variable Default Description
api_key MAXIMEM_API_KEY required Your Maximem API key.
endpoint MAXIMEM_ENDPOINT Maximem API Only needed for a non-default environment.
channel "unspecified" The name of your integration. Recommended.
agent_id "unspecified" Tag recorded on stored memories.
timeout 30.0 Request timeout in seconds.
max_retries 2 Retries for temporary failures. 0 disables them.
http_client managed Your own httpx.Client / httpx.AsyncClient (proxies, custom TLS, tests).

Arguments take precedence over environment variables.

API reference

Every method is available on VityClient and, as a coroutine, on AsyncVityClient.

Memory

Method Returns
recall(current_prompt, recent_messages=None, max_tokens=1000, strategy="hybrid") str: prompt-ready context, or ""
capture(messages, session_key="", agent_id="", channel=None) CaptureResult
store(content, memory_type="fact", category="", importance="medium") StoreResult: {"id", "stored"}
search(query, top_k=10, category="", min_score=0.0) list[SearchResult]: content, type, score, id, created_at
forget(query="", dry_run=True, delete_all=False) ForgetResult: {"count", "ids"}
capture_status(request_id) dict
  • strategy: "semantic", "recency" or "hybrid".
  • memory_type: fact, preference, emotion, episode, knowledge or profile. Use category (preference, fact, task, relationship, context) to set the category directly.
  • importance: "low", "medium" or "high".

Deleting memories

forget() only previews unless you pass dry_run=False. Deleting without a query removes all memories on the account, so it also requires delete_all=True:

client.forget("old employer")                    # preview what would be deleted
client.forget("old employer", dry_run=False)     # delete matching memories
client.forget(dry_run=False, delete_all=True)    # delete everything

Knowledge

Method Returns
knowledge(query="", limit=10, offset=0, min_score=0.3, filters=None, include=None, ...) KnowledgeResult
knowledge_diff(input_text, purpose, ...) KnowledgeDiffResult

knowledge() returns consolidated knowledge about the user (topics, summaries, confidence), with pagination through limit and offset. Filter with keys such as topic_category, confidence_min, seen_after and seen_before; choose sections with include ("items", "facets", "profile").

knowledge_diff() returns the knowledge most relevant to a piece of text. purpose describes what you are looking for and why:

client.knowledge_diff(
    input_text="Draft: proposal to move our analytics to ClickHouse",
    purpose="the user's earlier decisions and opinions about analytics databases",
)

Meetings

Method Returns
meetings_enabled() bool: False if unavailable
meeting_ask(question, max_memories=12, meeting_type="", status="", seed_person_id="") dict
get_meeting(external_id) dict
list_meeting_reviews() list[dict]

LLM tool calling

as_tool() lets a model search and save memories itself. It provides two tools, search_memory and save_memory, in OpenAI or Anthropic format:

from openai import OpenAI
from maximem_vity import VityClient

llm, vity = OpenAI(), VityClient(channel="assistant")
memory = vity.as_tool(style="openai")       # or style="anthropic"

messages = [{"role": "user", "content": "What am I allergic to?"}]
response = llm.chat.completions.create(model="gpt-4o", messages=messages, tools=memory.definitions)

for call in response.choices[0].message.tool_calls or []:
    if memory.handles(call.function.name):
        result = memory.call(call.function.name, call.function.arguments)
        messages.append({"role": "tool", "tool_call_id": call.id, "content": result})
  • definitions is plain JSON and can be passed directly as tools.
  • call() accepts arguments as a JSON string or a dict, and returns a JSON string.
  • If the model sends invalid arguments, call() returns {"error": ...} so the model can retry. Other problems, such as an invalid API key, raise an exception.
  • Pass read_only=True to offer only search_memory.
  • The model chooses the query or the fact to save. It cannot change whose memory is used.

With AsyncVityClient, use await memory.call(...).

Error handling

All exceptions inherit from VityError:

Exception Raised when
VityInvalidInputError An argument is invalid. Usually raised before any request is sent.
VityAuthError The API key is missing, invalid or revoked.
VityInsufficientCreditsError The account has run out of credits.
VityNotFoundError The requested item does not exist.
VityRateLimitError Too many requests. Check retry_after.
VityUnavailableError A temporary service or network problem, or a timeout.

Each exception has message, status_code, code, request_id, retry_after and retryable. Include request_id when contacting support.

import time
from maximem_vity import VityError, VityInsufficientCreditsError, VityRateLimitError

try:
    client.store("User is vegetarian", memory_type="preference")
except VityInsufficientCreditsError:
    ...  # prompt the account owner to add credits
except VityRateLimitError as err:
    time.sleep(err.retry_after or 60)
except VityError as err:
    print(f"Vity request failed: {err} (request id: {err.request_id})")

Retries and timeouts

The client retries temporary failures automatically, up to max_retries times with exponential backoff:

  • Read operations (recall, search, knowledge, ...) are retried after temporary errors.
  • Write operations (store, capture, forget) are retried only when the request never reached the service. This prevents a memory from being saved twice.
  • The client never waits more than a few seconds before retrying. If the service asks for a longer wait, you get a VityRateLimitError with retry_after set and can decide what to do.

Input is validated before sending. For example, capture() accepts up to 50 messages per call and store() up to 10,000 characters, so mistakes fail fast with a clear message.

Logs go to the maximem_vity logger: retries at WARNING, requests at DEBUG. The API key is never logged.

Testing

Use an httpx.MockTransport to test your code without network access:

import httpx
from maximem_vity import VityClient

def handler(request: httpx.Request) -> httpx.Response:
    return httpx.Response(200, json={"context": "User prefers dark mode", "sources": []})

client = VityClient(api_key="mx_test", http_client=httpx.Client(transport=httpx.MockTransport(handler)))
assert client.recall("theme?") == "User prefers dark mode"

Upgrading from 0.2.x

0.3.0 is backwards compatible for typical use. Check these changes:

  • user_id is deprecated. It is ignored because memory belongs to the account that owns the key. It will be removed in 0.4.0.
  • channel and agent_id default to "unspecified". Set channel to your integration's name.
  • Deleting everything requires confirmation: forget(dry_run=False, delete_all=True).
  • search(min_score=0.0) now means no minimum score, so you may see more results.
  • Invalid arguments raise VityInvalidInputError before any request is sent.
  • New exceptions VityInvalidInputError, VityInsufficientCreditsError and VityNotFoundError inherit from VityError, so existing except VityError blocks keep working.

License

MIT

Metadata

Release files for maximem-vity-sdk 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for maximem-vity-sdk 0.3.0
File Size Uploaded
maximem_vity_sdk-0.3.0.tar.gz 37.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for maximem-vity-sdk 0.3.0
File Interpreter ABI Platform
maximem_vity_sdk-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 66.5 kB

Release files / maximem_vity_sdk-0.3.0.tar.gz

Download URL maximem_vity_sdk-0.3.0.tar.gz
Size 37.9 kB
Tags Source
SHA-256 checksum
How to use checksums
15af0e1c9ba89ab7ad48dc0d5995c8b821fda67343999d9576724286e0ac989b
BLAKE2b-256 checksum
How to use checksums
549a3dadd07feae837ef7d476628239db590bed13f24c3cfbb5b42fd8e14d3b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.1

Release files / maximem_vity_sdk-0.3.0-py3-none-any.whl

Download URL maximem_vity_sdk-0.3.0-py3-none-any.whl
Size 28.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bad3a3ac20b385093e2409dbdc6201e193faecbd500a5f7a9a6f9ced2592729f
BLAKE2b-256 checksum
How to use checksums
13094be984abf5506d30b8ae56b300d8c459baef200208c8a57dfdb28ef25118
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.1

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page