Metadata-Version: 2.4
Name: zin
Version: 0.0.5
Summary: Ancient ground for modern agents. Minimal setup for long-term memory, auto feedback loop, agents CI/CD, auto tracing, and API serving.
Project-URL: Homepage, https://github.com/galsalo/zin
Project-URL: Repository, https://github.com/galsalo/zin
Project-URL: Issues, https://github.com/galsalo/zin/issues
Author: Gal Salomon
License-Expression: Elastic-2.0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.11
Requires-Dist: httpx>=0.28
Description-Content-Type: text/markdown

# Zin

Ancient ground for modern agents. Minimal setup for long-term memory, auto feedback loop, agents CI/CD, auto tracing, and API serving.

## Install

```bash
pip install zin
```

## Quick start

```python
import asyncio
from zin import ZinMemory

async def main():
    async with ZinMemory("http://localhost:8000") as client:
        # Add a memory
        mem_id = await client.add("Prefers dark mode", user_id="user-1")

        # Search by semantic similarity
        results = await client.search("UI preferences", user_id="user-1")
        for r in results:
            print(r.text, r.distance)

        # Process a conversation — the memory agent extracts and stores
        # relevant facts automatically (fire-and-forget on the server)
        await client.process_memory(
            messages=[
                ("user", "I just moved to Berlin"),
                ("assistant", "Nice! How are you settling in?"),
            ],
            user_id="user-1",
        )

asyncio.run(main())
```

## API reference

### `ZinMemory(base_url, timeout=10.0)`

Async client for the Zin memory server. Use as an async context manager or call `close()` when done.

### `await client.add(text, *, user_id=None, namespace="personal", metadata=None) -> str`

Store a memory. Returns the memory ID.

| Parameter   | Type            | Description                                    |
|-------------|-----------------|------------------------------------------------|
| `text`      | `str`           | The memory content                             |
| `user_id`   | `str \| None`   | Scopes to `personal_<user_id>` namespace       |
| `namespace` | `str`           | Target namespace (default: `"personal"`)       |
| `metadata`  | `dict \| None`  | Arbitrary metadata stored with the memory      |

### `await client.search(query, *, user_id=None, namespace=None, top_k=5) -> list[SearchResult]`

Semantic similarity search over stored memories.

| Parameter   | Type            | Description                                          |
|-------------|-----------------|------------------------------------------------------|
| `query`     | `str`           | Natural language search query                        |
| `user_id`   | `str \| None`   | Scope search to user's personal namespace            |
| `namespace` | `str \| None`   | Search a specific namespace                          |
| `top_k`     | `int`           | Max results to return (default: `5`)                 |

Returns a list of `SearchResult` objects with `id`, `text`, `metadata`, `namespace`, and `distance` fields.

### `await client.process_memory(messages, *, user_id=None, namespaces=None, store_personal=True) -> None`

Send a conversation window to the memory agent. The agent analyzes the conversation and autonomously creates, updates, or deletes memory records.

| Parameter        | Type                              | Description                                              |
|------------------|-----------------------------------|----------------------------------------------------------|
| `messages`       | `list[tuple[str, str]]`           | Conversation as `(role, content)` tuples                 |
| `user_id`        | `str \| None`                     | User ID for personal namespace scoping                   |
| `namespaces`     | `dict[str, str] \| None`         | Shared namespaces, e.g. `{"company": "Company knowledge"}` |
| `store_personal` | `bool`                            | Whether the agent can store personal memories (default: `True`) |

### `await client.list_memories(*, namespace=None, limit=100) -> list[Memory]`

List stored memories without vector search. Useful for debugging.

### `await client.delete_all_memories() -> int`

Delete all memories. Returns the count of deleted records.

## Namespaces

Zin uses a two-level namespace system:

- **Personal** (`personal`): Private per-user memory, resolved to `personal_<user_id>` on the server. This is the default namespace.
- **Shared**: Named namespaces passed via `namespaces` dict (e.g. `{"company": "Company-wide knowledge"}`). The memory agent decides which namespace to use based on content.

When searching without specifying a namespace, the search is scoped to the user's personal namespace (privacy-first default).

## Requirements

- Python >= 3.11
- A running [Zin server](https://github.com/galsalo/zin)

## License

[Elastic License 2.0 (ELv2)](https://github.com/galsalo/zin/blob/main/LICENSE)
