Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,35 @@

All notable changes to this project will be documented in this file.

## [0.1.0] - 2026-02-12
## [0.6.0] - 2026-05-08

- Initial SDK bootstrap with `uv` + `uv_build`.
- Added `src` package layout with typed `engram` sync/async client skeletons.
- Added ruff, mypy, pytest, pre-commit, CI, and release workflows.
- Added OIDC-based PyPI release workflow and contributor documentation.
- Added a `properties` parameter to `memories.add()` and `memories.search()` for attaching and filtering on arbitrary string key-value pairs (e.g. `conversation_id`).
- Added per-topic property filters via the new `Topic` model, letting search override or clear inherited global filters on a per-topic basis.

## [0.5.0] - 2026-03-20

- `memories.add()` now accepts a list of strings as input, producing one memory per string.
- Added `PreExtractedInput` and `PreExtractedItem` for callers that already have extracted facts and want to bypass the extraction step in the pipeline.

## [0.4.0] - 2026-03-10

- Standardised conversation input on the OpenAI Chat Completions format. Added `ConversationInput`, `MessageInput`, and the `ToolCallInput` / `ToolCallFuncInput` / `ToolCallCustomInput` models.
- Added `"fetch"` as a `retrieval_type` option on `RetrievalConfig`.

## [0.3.0] - 2026-03-05

- Updated input content types on `memories.add()`.
- Removed an unnecessary memory body wrapper from request payloads.

## [0.2.0] - 2026-03-02

- Updated request and response models for `memories.get()` and `memories.delete()`.
- README touch-up.

## [0.1.0] - 2026-02-20

- Initial functional release.
- Added `memories.add()`, `memories.get()`, `memories.delete()`, and `memories.search()`.
- Added `runs.get()` and `runs.wait()` for tracking the asynchronous pipeline.
- Sync (`EngramClient`) and async (`AsyncEngramClient`) clients.
- Initial SDK bootstrap with `uv` + `uv_build`, `src` package layout, typed `engram` client skeletons, ruff/mypy/pytest/pre-commit/CI, and OIDC-based PyPI release workflow.
110 changes: 85 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
<img src="https://raw.githubusercontent.com/weaviate/engram-python-sdk/main/docs/assets/weaviate-logo.png" alt="Weaviate" width="140" align="right" />

# weaviate-engram

> [!WARNING]
> **Engram is currently in preview.** While in preview (pre-1.0), the API is subject to breaking changes without notice. Use in production at your own risk.
[![PyPI version](https://img.shields.io/pypi/v/weaviate-engram.svg)](https://pypi.org/project/weaviate-engram/)
[![Python versions](https://img.shields.io/pypi/pyversions/weaviate-engram.svg)](https://pypi.org/project/weaviate-engram/)
[![License](https://img.shields.io/pypi/l/weaviate-engram.svg)](https://github.com/weaviate/engram-python-sdk/blob/main/LICENSE)
[![CI](https://github.com/weaviate/engram-python-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/weaviate/engram-python-sdk/actions/workflows/ci.yml)

The official Python SDK for **Engram**, the fully managed memory service by Weaviate.

Engram is a fully managed memory service by Weaviate. It lets you add persistent, personalized memory to AI assistants and agents — no infrastructure to set up or manage. When you add a memory, Engram processes it asynchronously through a background pipeline that extracts, deduplicates, and reconciles facts. Memories are scoped at three levels — project, user, and conversation — which can be mixed and matched freely. Each scope is backed by Weaviate's multi-tenant architecture, ensuring strong isolation between tenants.
Engram lets you add persistent, personalized memory to AI assistants and agents, with no infrastructure to set up or manage. When you add a memory, Engram processes it asynchronously through a background pipeline that extracts, deduplicates, and reconciles facts. Memories are scoped by project and user, along with any custom scope properties you define, and these scopes can be mixed and matched freely. Each scope is backed by Weaviate's multi-tenant architecture, ensuring strong isolation between tenants.

[Learn more about Engram →](https://weaviate.io/product/engram)

## Requirements

Expand All @@ -19,64 +27,116 @@ pip install weaviate-engram
uv add weaviate-engram
```

## Quick Start
## Get an API key

Engram runs on [Weaviate Cloud](https://console.weaviate.cloud). To get started:

Create a project and get an API key at [console.weaviate.cloud/engram](https://console.weaviate.cloud/engram).
1. **Sign up** (or log in) at [console.weaviate.cloud](https://console.weaviate.cloud).
2. **Open Engram** and create a project at [console.weaviate.cloud/engram](https://console.weaviate.cloud/engram).
3. **Generate an API key** from the project's **API Keys** page. Keys are shown once, so copy yours somewhere safe.

## Quick start

**1. Initialize the client**

```python
from engram import EngramClient

client = EngramClient(api_key="your-api-key")
client = EngramClient(api_key="YOUR_API_KEY")
```

**Add a memory from a string:**
**2. Add a memory from a string**

```python
run = client.memories.add("Alice prefers async Python and avoids Java.", user_id="user_123")
# add() returns immediately. Memory processing happens asynchronously
# in the background via Engram's pipeline.
run = client.memories.add(
"User prefers concise responses and dark mode",
user_id="alice@example.com",
)
print(run.run_id) # e.g. "run_abc123"
```

**Add a memory from a conversation:**
**3. Add a memory from a conversation**

Conversations use the OpenAI Chat Completions message format. Separately, you can pass scope `properties` to control where a memory lives — here a `conversation_id` scopes it to a specific session. Properties work with any input type, not just conversations:

```python
run = client.memories.add(
[
{"role": "user", "content": "What's the best way to handle retries?"},
{"role": "assistant", "content": "Exponential backoff with jitter is the standard approach."},
{"role": "user", "content": "Got it — I'll use that in my HTTP client."},
{"role": "user", "content": "I just moved to Berlin and I am looking for a good coffee shop."},
{"role": "assistant", "content": "Welcome to Berlin! Here are some popular coffee shops in the city..."},
{"role": "user", "content": "I prefer specialty coffee, not chains."},
],
user_id="user_123",
user_id="alice@example.com",
properties={"conversation_id": "session-abc123"},
)

print(run.run_id) # e.g. "run_abc123"
```

**Search memories:**
**4. Search memories**

```python
results = client.memories.search(query="What does Alice think about Python?", user_id="user_123")
results = client.memories.search(
query="What does the user prefer?",
user_id="alice@example.com",
)
for memory in results:
print(memory.content)
```

**Wait for a run to complete** (memory processing is asynchronous):
## Async client

An async client with the same surface is available:

```python
status = client.runs.wait(run.run_id, timeout=60.0)
print(status.status) # "completed" or "failed"
print(f"+{len(status.memories_created)} ~{len(status.memories_updated)} -{len(status.memories_deleted)}")
from engram import AsyncEngramClient

client = AsyncEngramClient(api_key="YOUR_API_KEY")

run = await client.memories.add(
"User prefers concise responses and dark mode",
user_id="alice@example.com",
)
results = await client.memories.search(
query="What does the user prefer?",
user_id="alice@example.com",
)
```

## Async Client
## Error handling

An async client is also available:
All SDK exceptions inherit from `EngramError`:

```python
from engram import AsyncEngramClient
from engram import (
APIError, # raised on any non-2xx response
AuthenticationError, # 401, invalid or missing API key
ValidationError, # invalid client configuration or request input
ConnectionError, # network failure reaching the Engram API
EngramTimeoutError, # runs.wait() did not reach a terminal status in time
)
```

## Waiting for a run to complete

client = AsyncEngramClient(api_key="your-api-key")
Each run is processed asynchronously. Under normal conditions you should **not** wait on runs — treat `add()` as fire-and-forget to keep latency low and let the pipeline reconcile memories in the background. Blocking on every run defeats the purpose of the async pipeline and will slow your application down, especially when ingesting at volume.

run = await client.memories.add("Alice prefers async Python and avoids Java.", user_id="user_123")
results = await client.memories.search(query="What does Alice think about Python?", user_id="user_123")
`runs.wait()` exists for the cases where you genuinely need the outcome of a specific run before proceeding — primarily debugging and tests:

```python
status = client.runs.wait(run.run_id, timeout=60.0)
print(status.status) # "completed" or "failed"
print(f"+{len(status.memories_created)} ~{len(status.memories_updated)} -{len(status.memories_deleted)}")
```

## Learn more

- **Product page:** [weaviate.io/product/engram](https://weaviate.io/product/engram)
- **Weaviate Cloud console:** [console.weaviate.cloud/engram](https://console.weaviate.cloud/engram)
- **Sign up:** [console.weaviate.cloud](https://console.weaviate.cloud)

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md).
Expand Down
Binary file added docs/assets/weaviate-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ license = "BSD-3-Clause"
authors = [{ name = "Weaviate" }]
keywords = ["engram", "sdk", "weaviate"]
classifiers = [
"Development Status :: 3 - Alpha",
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Programming Language :: Python :: 3",
Expand Down