Metadata-Version: 2.5
Name: pydantic-ai-dynamodb-memory
Version: 0.1.0
Summary: Amazon DynamoDB MemoryStore for the PydanticAI harness Memory capability — CAS versions and idempotent operation receipts via conditional writes
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,aws,dynamodb,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: boto3
Requires-Dist: pydantic-ai-memory-core>=0.1.0
Description-Content-Type: text/markdown

# pydantic-ai-dynamodb-memory

An **Amazon DynamoDB** `MemoryStore` for the [PydanticAI harness](https://pydantic.dev/docs/ai/harness/memory/) `Memory` capability — the per-user Markdown notebook the harness injects before every model call and lets the model write through `write_memory`, on a shared, durable table.

```bash
pip install pydantic-ai-dynamodb-memory
```

```python
from dataclasses import dataclass
from pydantic_ai import Agent
from pydantic_ai_harness.memory import Memory
from pydantic_ai_dynamodb_memory import DynamoDBMemoryStore

@dataclass
class Deps:
    user_id: str

store = DynamoDBMemoryStore(table_name="agent-memory")          # table auto-created (PAY_PER_REQUEST)
agent = Agent("anthropic:claude-sonnet-5", deps_type=Deps,
              capabilities=[Memory(store=store, namespace=lambda ctx: ctx.deps.user_id)])

agent.run_sync("I moved to Hanoi and hate early flights.", deps=Deps("kamal"))   # model calls write_memory
agent.run_sync("Book me something to Bangkok.", deps=Deps("kamal"))              # MEMORY.md injected first
```

## How it works

- One table, `pk` = `f#<path>` for memory files (`content`, `version`, `operation_id`) and `o#<operation id>` for operation receipts. Auto-created; pass `create_table=False` to manage it yourself.
- **Compare-and-swap** is a DynamoDB conditional write: create requires `attribute_not_exists(pk)`, replace and delete require `version = :expected`. A stale version raises the harness `MemoryConflictError`, never an overwrite.
- **Operation receipts** (`MemoryOperation`) are reserved with a conditional put, completed after the mutation, and dropped if the mutation fails, so durable-execution replays return the original result and a reused id with different arguments raises `MemoryOperationConflictError`.
- `search` is the harness's bounded lexical search over the scope's files (`SearchableMemoryStore`); `list_paths` is a prefix scan, sized for notebook volumes.
- Async protocol methods run the boto3 calls in a worker thread.

Writing to memory from outside the model, e.g. from the [`agentstate-reducer` `on_prune` hook](https://skamalj.github.io/agentstate-reducer/reducer/long-term-memory/): `await append_memory(store, f"{user_id}/main/facts.md", text)` from `pydantic-ai-memory-core` does a CAS-safe append with retries.

Permissions: `DescribeTable`, `CreateTable`, `GetItem`, `PutItem`, `UpdateItem`, `DeleteItem`, `Scan`.

Docs: <https://skamalj.github.io/agentstate-reducer/> · part of [pydantic-ai-memory](https://github.com/skamalj/pydantic-ai-memory)

## License

MIT
