Metadata-Version: 2.5
Name: ag2-memorysync
Version: 1.0.1
Summary: MemorySync for AG2 (AutoGen classic): an automatic memory loop on ConversableAgent's hook system — budgeted recall injection, duplicate-proof both-side capture, and a deadlock-free sync bridge.
Project-URL: Homepage, https://docs.memorysync.io/guides/ag2
Project-URL: Documentation, https://docs.memorysync.io/guides/ag2
Project-URL: Repository, https://github.com/memorysyncio/memorysync-plugins
Author-email: MemorySync <support@memorysync.io>
License-Expression: MIT
Keywords: ag2,agents,autogen,conversableagent,long-term-memory,memory,memorysync
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
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 :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Requires-Dist: httpx<1,>=0.25
Description-Content-Type: text/markdown

# ag2-memorysync

[MemorySync](https://memorysync.io) for [AG2](https://github.com/ag2ai/ag2-classic)
(the classic AutoGen `ConversableAgent` framework, `pip install autogen`):
an automatic memory loop — recall injected before every reply, both sides
persisted, zero extra code per turn.

```bash
pip install ag2-memorysync
```

## Quick start

```python
from autogen import ConversableAgent
from ag2_memorysync import MemorySyncCapability

assistant = ConversableAgent("assistant", llm_config=...)

memory = MemorySyncCapability(
    api_key="ms_...",              # or MEMORYSYNC_API_KEY
    user_id="customer-42",         # required — who these memories belong to
    session_id="support-chat",     # scopes the transcript
)
memory.add_to_agent(assistant)     # that's the whole integration
```

From then on every incoming user message is persisted and enriched with
recalled context, and every outgoing reply is persisted — through AG2's
own hook system (`process_last_received_message` +
`process_message_before_send`).

## Why this one

| | Mem0 | Zep (`zep-ag2`) | **MemorySync** |
| --- | --- | --- | --- |
| AG2 adapter exists | ✗ docs show an AutoGen-0.2 recipe with placeholder model names | ✓ | ✓ |
| Multi-agent duplication | — | ✗ **documented bug**: two attached agents store every utterance twice with conflicting roles | ✓ cross-hook dedup registry + idempotency seeds — one utterance, one row (by test) |
| Sync→async bridge | — | per-call event-loop spin; documented deadlock caveat under asyncio | ✓ one persistent background loop; never touches the caller's loop (asyncio-driven chats pass, by test) |
| Recall latency budget | — | ✗ none | ✓ hard 1.2s default — the reply is never late |
| Framework pin | — | ✗ `ag2<1` — breaks on the v1 rewrite | ✓ **zero framework dependency** (duck-typed attach; works with whichever classic distribution you installed) |
| Injected context re-stored? | — | system-message mutation, last-write-wins | ✓ hook output feeds the LLM only; the ORIGINAL text is what persists |

## Semantics worth knowing

- **The reply is never stalled and never broken.** Recall blocks at most
  `recall_timeout` (default 1.2s); persistence is fire-and-forget off
  the hot path. Outages and quota exhaustion degrade to "no memories
  this turn".
- Turns store verbatim under the `ag2::<session>` transcript scope with
  deterministic idempotency seeds — retries and multi-agent echoes
  converge on one stored row.
- Tool/function messages are never persisted.
- `register_memory_tools(memory, caller=..., executor=...)` adds
  `search_memory` + `save_memory` tools (the caller needs an
  `llm_config`, as usual for AG2 tools).
- `memory.flush()` waits for in-flight writes (shutdown/tests);
  `memory.close()` flushes and releases the HTTP client.

## Configuration

| Parameter | Default | Meaning |
| --- | --- | --- |
| `user_id` | — (required) | End user the memories belong to |
| `session_id` | `"default"` | Transcript scope |
| `top_k` | `5` | Memories considered per turn |
| `recall_timeout` | `1.2` | Hard recall budget, seconds |
| `min_prompt_chars` | `8` | Skip recall for trivial messages |
| `context_template` | built-in | `{context}` placeholder, brace-safe `.replace` rendering |
| `capture` | `"both"` | `"received"` / `"sent"` to capture one side only |

## Development

```bash
pip install -e . "autogen[openai]" pytest
python -m pytest tests -q      # 22 tests through REAL ConversableAgent chats
```

The suite includes a reproduction of zep-ag2's documented multi-agent
double-store scenario (we store once) and a chat driven from inside
`asyncio.run()` (no deadlock).

## License

MIT
