eemario opened a new issue, #1313:
URL: https://github.com/apache/flink-agents/issues/1313

   ### Search before asking
   
   - [x] I searched in the 
[issues](https://github.com/apache/flink-agents/issues) and found nothing 
similar.
   
   ### Description
   
   Found during the documentation walkthrough in #1283.
   
   A `MemorySet` is bound to the Action context that obtained it. Long-Term 
Memory operations are expected to be scoped by the job identifier, partition 
key, and memory-set name.
   
   List, search, and whole-set deletion pass that scope to Mem0 as `user_id`, 
`agent_id`, and `run_id`. However, operations with explicit IDs call Mem0 only 
by `memory_id`:
   
   ```python
   result = self._mem0_instance.get(memory_id=memory_id)
   self._mem0_instance.delete(memory_id=memory_id)
   ```
   
   Mem0 retrieves these records directly by vector ID, and Flink Agents does 
not verify that the returned record belongs to the calling `MemorySet`. If an 
ID from another context is available, `get(ids=...)` may read it and 
`delete(ids=...)` may delete it.
   
   The Java API has the same behavior because it delegates these operations to 
the Python implementation.
   
   ### How to reproduce
   
   Use two `MemorySet`s with the same job identifier and set name but different 
partition keys:
   
   1. A adds an item and obtains its ID.
   2. B's ordinary `get()` returns no items, but `get(ids=...)` reads A's item.
   3. B's `delete(ids=...)` deletes it; A's ordinary `get()` now returns no 
items.
   
   <details>
   <summary>Runnable reproduction (repository root, using 
python/.venv)</summary>
   
   Uses real Mem0/Chroma storage with mocked models and runner context; no 
external services are required. All operations run sequentially.
   
   ```bash
   PYTHONPATH="python:$(python/.venv/bin/python -c 'import sysconfig; 
print(sysconfig.get_paths()["purelib"])')" python/.venv/bin/python - <<'PY'
   import os
   from tempfile import TemporaryDirectory
   from unittest.mock import create_autospec
   
   with TemporaryDirectory(dir=".") as tmp:
       os.environ["MEM0_DIR"] = tmp
       os.environ["MEM0_TELEMETRY"] = "false"
       os.environ["ANONYMIZED_TELEMETRY"] = "false"
   
       from flink_agents.api.runner_context import RunnerContext
       from flink_agents.integrations.vector_stores.chroma.chroma_vector_store 
import (
           ChromaVectorStore,
       )
       from flink_agents.runtime.memory.mem0.mem0_long_term_memory import (
           Mem0LongTermMemory,
       )
       from flink_agents.runtime.memory.mem0.tests.test_mem0_long_term_memory 
import (
           MockChatModelSetup,
           MockEmbeddingModelSetup,
       )
   
       resources = {
           "chat": MockChatModelSetup(),
           "embedding": MockEmbeddingModelSetup(),
           "store": ChromaVectorStore(
               embedding_model="embedding",
               collection="ltm_id_scope_repro",
           ),
       }
       ctx = create_autospec(RunnerContext, instance=True)
       ctx.agent_metric_group = None
       ctx.get_resource.side_effect = lambda name, resource_type: 
resources[name]
   
       def get_set(key):
           ltm = Mem0LongTermMemory(
               ctx=ctx,
               job_id="job",
               chat_model_name="chat",
               embedding_model_name="embedding",
               vector_store_name="store",
               mailbox_thread_checker=lambda: None,
           )
           ltm.switch_context(key, observation_id=key)
           return ltm.get_memory_set("preferences")
   
       owner = get_set("key-a")
       other = get_set("key-b")
       ids = owner.add("The owner prefers tea.")
       assert len(ids) == 1 and len(owner.get()) == 1
       assert other.get() == []
       assert other.get(ids=ids)[0].value == "The owner prefers tea."
       other.delete(ids=ids)
       assert owner.get() == []
       print("Reproduced: B read and deleted A's item by ID.")
   PY
   ```
   
   Expected output on the affected version (apart from a dependency warning):
   
   ```text
   Reproduced: B read and deleted A's item by ID.
   ```
   
   </details>
   
   ## Expected behavior
   
   ID-based operations should enforce the scope bound to the calling 
`MemorySet`:
   
   ```text
   record.user_id == current job identifier
   record.agent_id == memory_set.partition_key
   record.run_id == memory_set.name
   ```
   
   An out-of-scope item should not be returned or deleted, preferably with 
behavior indistinguishable from an unknown ID. For example:
   
   - `get(ids=...)` skips out-of-scope and unknown IDs and returns only the 
in-scope items.
   - `delete(ids=...)` checks the whole batch first and, if any ID is out of 
scope or unknown, raises Mem0's not-found `ValueError` without deleting 
anything.
   
   The unknown-ID behavior needs a related fix. Today an unknown ID makes both 
operations fail with an `AttributeError`: for a missing ID, the Flink Agents 
vector-store adapter returns an empty `OutputData` instead of `None`, so Mem0's 
not-found handling never runs.
   
   The fix should cover Java and Python. Mem0 already returns `user_id`, 
`agent_id`, and `run_id` from `get(memory_id)`, so the check can be done in 
Flink Agents without relying on vector-store filters.
   
   ## Actual behavior
   
   The runtime verifies that the `MemorySet` has a non-empty partition key, but 
its bound job/key/set scope is not used to authorize ID-based reads or deletes. 
Observation records are still attributed to the calling context, which may also 
make audit output misleading.
   
   cc @weiqingy @wenjin272 — could you please confirm whether ID-based 
`MemorySet.get/delete` operations are expected to enforce the bound job, 
partition-key, and memory-set scope?
   
   ### Version and environment
   
   - Source: `main` at `60bf8cd0`
   - Python: 3.11.15
   - `mem0ai`: 1.0.11
   - `chromadb`: 1.0.21
   - Platform: macOS arm64
   - Reproduction invokes `Mem0LongTermMemory` directly with the repository's 
mock chat and embedding models and real Mem0/Chroma storage; no external model 
service or Flink cluster is required.
   
   ### Are you willing to submit a PR?
   
   - [x] I'm willing to submit a PR!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to