Metadata-Version: 2.4
Name: wontopos
Version: 2.2.7
Summary: Wontopos — long-term memory for AI agents. Pure semantic retrieval, identical recall in every language, ~100× lower LLM bill.
Author: Wontopos
License: MIT
Project-URL: Homepage, https://wontopos.com
Project-URL: Documentation, https://wontopos.com/why
Project-URL: Repository, https://github.com/Irina1920/Wos_API
Project-URL: Issues, https://github.com/Irina1920/Wos_API/issues
Keywords: memory,ai,agent,llm,vector,embedding,semantic,rag,context
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28
Dynamic: license-file

# Wontopos — long-term memory for AI agents

```bash
pip install wontopos
```

```python
from wontopos import Client

mem = Client(api_key="wos-...")
mem.add("she prefers tea over coffee", user_id="alice")

# one call → short-term + long-term + context, ready for your LLM prompt
ctx = mem.recall("what does alice drink?", user_id="alice")
```

## Why

- **Pure semantic retrieval** — no keyword/BM25. Identical recall in every language (한국어 · 日本語 · 中文 · English).
- **No LLM in the loop** — `store` / `search` / `recall` never call a language model. You pay embeddings, not generation.
- **Bounded retrieval** — `recall()` returns a small, fixed-size slice (~1,200 tokens) regardless of how much you've stored. Your LLM bill stops growing with history.

## Methods

| Method | Purpose |
|---|---|
| `add(content, user_id, **metadata)` | Store one memory |
| `add_turn(user_msg, assistant_msg, user_id?)` | Store a conversation exchange |
| `add_bulk(content, user_id, category=, timestamp=)` | Backfill a long history |
| `update(old_memory_id, new_content, user_id?)` | Supersede an old fact |
| `search(query, user_id, limit=10, **opts)` | Semantic search |
| `recall(query, user_id)` | One-call context (short + long + surrounding) |
| `history(user_id)` | Recent turns (short-term) |
| `stats(user_id)` | Counts |
| `delete(user_id, memory_id)` | Delete one memory |
| `delete_all(user_id)` | GDPR erase (delete every memory for the user) |
| `add_speaker(speaker, user_id?)` | Register a person (explicit, up to 50 to start) |
| `list_speakers(user_id?)` | Registered people + per-person memory counts |
| `remove_speaker(speaker, user_id?)` | Unregister; memories stay, the tag goes |

All methods take a `user_id` — it names the **store**: one isolated memory space per end-user, agent, or topic, then per account (your API key). WHO said each memory inside a store is the `speaker` tag below — storing the assistant's own words never needs a separate id.

## Who said it (speakers)

Every memory can carry a speaker: `"me"` for the assistant's own words, or a
person's name. Speakers are explicit, like stores: register a person once,
then store under their name — a typo can never silently become a new person.
Search accepts a speaker too, so you can recall one person's words only.

```python
mem.add_speaker("Bob", user_id="alice")      # once per person
mem.add("I promised to send the report on Friday", user_id="alice", speaker="me")
mem.add("Bob said the deadline moved to Tuesday", user_id="alice", speaker="Bob")
mem.search("what did Bob say about deadlines?", user_id="alice", speaker="Bob")
```

A store registers up to 50 people to start (a limit we plan to raise);
`"me"` never needs registration and never counts against it.

## Recall caching

Opt in per search and repeated or extended queries reuse the previous result
at 10% of the normal rate (Tablet and Scroll models):

```python
hits = mem.search("...the conversation so far...", user_id="alice",
                  cache_control={"ttl": "5m"})   # or "1h"
```

## Errors

Any non-2xx response raises `WosError(status, message)`:

```python
from wontopos import Client, WosError

try:
    mem.search("...", user_id="alice")
except WosError as e:
    if e.status == 401:
        print("API key invalid or revoked")
    elif e.status == 429:
        print("Rate limited — back off")
    else:
        print(e.status, e.message)
```

## Self-host

Point at your own engine:

```python
mem = Client(api_key="...", base_url="https://wos.your-host.com")
```

## Links

- Homepage: <https://wontopos.com>
- API reference: <https://wontopos.com/why> (Developers tab)
- Repo: <https://github.com/Irina1920/Wos_API>

License: MIT.
