Metadata-Version: 2.5
Name: pydantic-ai-memory-core
Version: 0.1.0
Summary: Shared core for PydanticAI harness MemoryStore backends — CAS versions, idempotent operation receipts and bounded search over a few conditional primitives
Project-URL: Homepage, https://github.com/skamalj/pydantic-ai-memory
Project-URL: Repository, https://github.com/skamalj/pydantic-ai-memory.git
Project-URL: Documentation, https://skamalj.github.io/agentstate-reducer/
Author-email: Kamal <skamalj@gmail.com>
Keywords: agent-memory,long-term-memory,memory,memorystore,pydantic-ai,pydantic-ai-harness
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Requires-Dist: anyio>=4
Requires-Dist: pydantic-ai-harness>=0.7.0
Description-Content-Type: text/markdown

# pydantic-ai-memory-core

Shared core for building [PydanticAI harness](https://pydantic.dev/docs/ai/harness/memory/) **`MemoryStore`** backends. The harness `Memory` capability injects a per-user Markdown notebook (`MEMORY.md` plus topic files) before every model call and lets the model write to it through `write_memory`; the store underneath must provide **compare-and-swap versions** and **idempotent operation receipts**. `KVMemoryStore` implements that whole protocol — `read` / `get_operation` / `write` / `delete` / `list_paths` and the optional `SearchableMemoryStore.search` — so a backend supplies only conditional primitives:

```python
from pydantic_ai_memory_core import KVMemoryStore

class MyStore(KVMemoryStore):
    def _get_file(self, path): ...                                         # -> {"content","version","operation_id"} | None
    def _create_file(self, path, content, version, operation_id): ...      # -> bool, only if absent
    def _replace_file(self, path, content, version, operation_id, expected_version): ...  # -> bool, only if version matches
    def _delete_file(self, path, expected_version): ...                    # -> bool
    def _list_paths(self, prefix, limit): ...                              # sorted
    def _get_receipt(self, op_id): ...                                     # -> {"fingerprint","version","existed","completed"} | None
    def _reserve_receipt(self, op_id, fingerprint): ...                    # -> bool, only if absent
    def _complete_receipt(self, op_id, version, existed): ...
    def _drop_receipt(self, op_id): ...
```

Each conditional primitive must be atomic in the backend (conditional write, ETag match or transaction); the core turns them into the harness contract. Use it with an agent:

```python
from pydantic_ai import Agent
from pydantic_ai_harness.memory import Memory

agent = Agent("anthropic:claude-sonnet-5", deps_type=Deps,
              capabilities=[Memory(store=MyStore(...), namespace=lambda ctx: ctx.deps.user_id)])
```

`append_memory(store, path, text)` is a CAS-safe append with retries for writing to memory from *outside* the model, for example from the [`agentstate-reducer` `on_prune` hook](https://skamalj.github.io/agentstate-reducer/reducer/long-term-memory/).

`pydantic_ai_memory_core.contract` is an importable test suite every provider runs, including an end-to-end pass through the real `Memory` capability on a PydanticAI `Agent` with a scripted model (no LLM). `pydantic_ai_memory_core.testing.InMemoryKVMemoryStore` is the reference backend.

Concrete backends: [`pydantic-ai-dynamodb-memory`](https://pypi.org/project/pydantic-ai-dynamodb-memory/), [`pydantic-ai-cosmosdb-memory`](https://pypi.org/project/pydantic-ai-cosmosdb-memory/), [`pydantic-ai-firestore-memory`](https://pypi.org/project/pydantic-ai-firestore-memory/), [`pydantic-ai-postgres-memory`](https://pypi.org/project/pydantic-ai-postgres-memory/).

Docs: <https://skamalj.github.io/agentstate-reducer/>

## License

MIT
