Python SDK

Install, initialize, and use the ConvoMem Python SDK.

The ConvoMem Python SDK supports Python 3.9+ with both sync and async clients.

Install

pip install convomem
 
# or with uv
uv add convomem

Initialize

import os
from convomem import ConvoMem
 
client = ConvoMem(api_key=os.environ["CONVOMEM_API_KEY"])

Optional configuration:

client = ConvoMem(
    api_key=os.environ["CONVOMEM_API_KEY"],
    timeout=10.0,    # seconds (default 10)
    max_retries=3,   # retries on 429 / 5xx
)

Identity

Every method accepts a CustomerIdentity that tells ConvoMem which customer to read or write. If customer_id is set, the SDK routes to the direct /customers/:id/… endpoint. Otherwise the server resolves the customer from email, phone, or external_id.

from convomem import CustomerIdentity
 
# By known ID — most direct
identity = CustomerIdentity(customer_id="cust_uuid_123")
 
# By email — server resolves the customer
identity = CustomerIdentity(email="[email protected]")
 
# By phone (E.164 format recommended)
identity = CustomerIdentity(phone="+14155550100")
 
# By external system ID
identity = CustomerIdentity(external_id="crm-456")

Capture

Send conversation turns for background memory extraction. Fire-and-forget — memories become searchable within seconds.

client.capture(
    messages=[
        {"role": "user",      "content": "I need help with my order"},
        {"role": "assistant", "content": "Of course, let me look that up."},
    ],
    CustomerIdentity(email="[email protected]"),
    channel="CHAT",
)

Look up context

Recall semantically relevant memories before generating a reply.

ctx = client.lookup(
    "order and shipping preferences",
    CustomerIdentity(email="[email protected]"),
)
 
print(ctx.context)          # prompt-ready context string
for mem in ctx.memories:
    print(f"  - {mem.content}")

Agent loop pattern

from convomem import ConvoMem, CustomerIdentity
 
client = ConvoMem(api_key="sk-org-…")
 
def handle_message(user_msg: str, email: str, conv_id: str | None = None):
    identity = CustomerIdentity(email=email)
 
    # 1. Recall context
    ctx = client.lookup("customer support", identity)
 
    # 2. Build prompt + call your LLM
    reply = call_llm(ctx.context, user_msg)
 
    # 3. Capture the turns
    result = client.capture(
        messages=[
            {"role": "user",      "content": user_msg},
            {"role": "assistant", "content": reply},
        ],
        identity,
        channel="CHAT",
    )
 
    return reply, result.conversation_id

Memories

from convomem import CustomerIdentity
 
identity = CustomerIdentity(customer_id="cust_uuid_123")
 
# List all memories
result = client.list_memories(identity, page=1, limit=20)
for mem in result.memories:
    print(f"- {mem.content}")
 
# Add manually
memory = client.add_memory(
    "Prefers email contact",
    identity,
    category="preference",
)
 
# Update (requires customer_id)
client.update_memory(
    "mem_uuid_456",
    identity,
    content="Prefers email and text contact",
)
 
# Delete (requires customer_id)
client.delete_memory("mem_uuid_456", identity)

Customers

from convomem import CustomerIdentity
 
# Create
customer = client.create_customer(
    name="Alice",
    email="[email protected]",
)
 
# Get by any identity
customer = client.get_customer(CustomerIdentity(email="[email protected]"))
print(f"Customer ID: {customer.id}")
 
# Update — by ID (direct) or by identity (server resolves)
updated = client.update_customer(
    CustomerIdentity(customer_id="cust_uuid_123"),
    name="Alice Smith",
)
 
# List
result = client.list_customers(page=1, limit=20)
print(f"{len(result.customers)} of {result.total}")
 
# Stats
stats = client.get_stats()
print(f"Total customers: {stats.total_customers}")
print(f"Total memories:  {stats.total_memories}")
 
# Delete
client.delete_customer(CustomerIdentity(customer_id="cust_uuid_123"))

Conversations

from convomem import CustomerIdentity
 
identity = CustomerIdentity(customer_id="cust_uuid_123")
 
# Start
conversation = client.start_conversation(identity, "CHAT")
print(f"Conversation: {conversation.id}")
 
# List
result = client.list_conversations(identity, page=1, limit=20)
 
# End — path-based when both IDs are known
client.end_conversation(
    "conv_uuid_456",
    identity,
    outcome="Resolved billing issue",
)
 
# End — flat route when only identity is known
client.end_conversation(
    None,
    CustomerIdentity(email="[email protected]"),
    outcome="Resolved",
)
 
# Escalate
client.escalate_conversation(
    "conv_uuid_456",
    identity,
    reason="Complex billing dispute",
)

Handoff

Generate a briefing for the human agent taking over the conversation.

handoff = client.get_handoff(CustomerIdentity(email="[email protected]"))
 
print(f"Narrative: {handoff.narrative}")
for mem in handoff.key_memories:
    print(f"  - {mem.content}")

Embed tokens

result = client.create_embed_token(
    CustomerIdentity(customer_id="cust_uuid_123"),
    ttl_seconds=3600,
)
 
print(f"Token: {result.token}")
print(f"Expires in: {result.expires_in}s")

Error handling

from convomem import ConvoMemApiError
 
try:
    customer = client.get_customer(CustomerIdentity(customer_id="cust_uuid_123"))
except ConvoMemApiError as e:
    print(f"Status: {e.status}")
    print(f"Body: {e.body}")

Async client

import asyncio
import os
from convomem import AsyncConvoMem, CustomerIdentity
 
async def main():
    async with AsyncConvoMem(api_key=os.environ["CONVOMEM_API_KEY"]) as client:
        ctx = await client.lookup(
            "billing question",
            CustomerIdentity(email="[email protected]"),
        )
        print(ctx.context)
 
        await client.capture(
            messages=[{"role": "user", "content": "What's my invoice?"}],
            identity=CustomerIdentity(email="[email protected]"),
            channel="CHAT",
        )
 
asyncio.run(main())

Low-level resource client

For advanced use cases (webhook integrations, raw resource access) you can use ConvoMemClient directly:

from convomem import ConvoMemClient, CaptureRequest, Message
 
client = ConvoMemClient(api_key="sk-org-…")
 
result = client.capture(CaptureRequest(
    messages=[Message(role="user", content="Hello")],
    email="[email protected]",
))

Other SDKs