Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions _pr_body_7748.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## Summary

Implementation of the `SharedMemoryStore` proposed in #7748 — a cross-agent shared memory store with scoped FTS recall for `autogen-ext`.

- **SQLite + FTS5 backend**, zero external dependencies (uses Python's built-in `sqlite3`)
- **Three scopes**: `agent` (private), `group` (per-team), `global` (cross-runtime)
- **Tool-shaped capsule recall** via `memory_search` / `memory_remember` / `memory_forget` — facts land in tool-result position, not prefix-loaded
- **Provenance on every read**: `created_by`, `scope`, `confidence`, `timestamp`, `fact_hash` — so consuming agents can distinguish claims from verified facts
- **Write authorization**: per-scope policy; `global` writes restricted by default (addressing the memory-poisoning concerns from @msaleme and @redbotster in #7748)
- **Soft-delete with tombstones** for audit trail
- **Configurable max capsule size** to bound recall payload

### v1 scope (per discussion in #7748)

This PR covers the minimal v1 shape the community converged on:
- [x] Global + group + agent scopes with FTS-only search (no embeddings)
- [x] Write receipts with provenance metadata
- [x] Per-scope write authorization
- [x] Optimistic concurrency via version field
- [x] `FunctionTool` factories for easy agent integration
- [x] Implements the `Memory` protocol — works with `AssistantAgent(memory=[...])`
- [ ] `should_recall_memory` policy hook (deferred — needs runtime integration discussion)
- [ ] Embedding column (intentionally deferred; FTS-first per @scosemicolon's suggestion)

## Test plan

- [x] 20 tests passing covering:
- Remember/search round-trip with provenance
- Scope isolation (agent facts invisible to other agents)
- Group scope sharing across agents
- Global write authorization (denied for unauthorized, allowed for authorized)
- Soft-delete with tombstone preservation
- Capsule size truncation
- TTL expiry
- Memory protocol compliance (`add`, `query`, `clear`)
- FunctionTool integration (search, remember, forget via `run_json`)
- File-backed SQLite persistence across store instances
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from ._config import MemoryScope, SharedMemoryConfig, WritePolicyEntry
from ._store import SharedMemoryStore, WriteReceipt
from ._tools import make_memory_tools

__all__ = [
"MemoryScope",
"SharedMemoryConfig",
"SharedMemoryStore",
"WriteReceipt",
"WritePolicyEntry",
"make_memory_tools",
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from __future__ import annotations

from enum import Enum
from typing import Dict, List, Optional

from pydantic import BaseModel, Field


class MemoryScope(str, Enum):
AGENT = "agent"
GROUP = "group"
GLOBAL = "global"


class WritePolicyEntry(BaseModel):
allowed_agents: List[str] = Field(default_factory=lambda: ["*"])


class SharedMemoryConfig(BaseModel):
db_path: str = Field(
default=":memory:",
description="Path to SQLite database file. Use ':memory:' for in-memory store.",
)
default_top_k: int = Field(default=5, ge=1, le=50)
max_capsule_bytes: int = Field(
default=2048,
description="Maximum size in bytes for a single recall capsule.",
)
write_policies: Dict[str, WritePolicyEntry] = Field(
default_factory=lambda: {
"agent": WritePolicyEntry(allowed_agents=["*"]),
"group": WritePolicyEntry(allowed_agents=["*"]),
"global": WritePolicyEntry(allowed_agents=[]),
},
description="Per-scope write authorization. Empty list = no one can write; ['*'] = open.",
)
group_id: Optional[str] = Field(
default=None,
description="Group identifier for group-scoped facts. Required when using group scope.",
)
Loading