Skip to content

fix(memory): honor read_only on update and recall access times (#7368) - #7369

Merged
Vidit-Ostwal merged 4 commits into
crewAIInc:mainfrom
roli-lpci:fix/read-only-blocks-update-issue-7368
Sep 15, 2026
Merged

Vidit-Ostwal merged 4 commits into
crewAIInc:mainfrom
roli-lpci:fix/read-only-blocks-update-issue-7368

Conversation

@roli-lpci

Copy link
Copy Markdown
Contributor

Fixes #7368.

Summary

Memory.read_only currently blocks remember and remember_many, but update still rewrites records and recall still persists last_accessed via touch_records. This change makes those two implicit mutation paths honor read_only while leaving explicit deletion through forget and reset unchanged.

Why

A caller using Memory as a read-only retrieval surface should not leave a persistent trace merely by reading. The existing read barrier and reset guards show that the omitted checks were inconsistent with the flag rather than an intentional latency exemption.

Tests

  • Added regression coverage proving update is a no-op in read-only mode.
  • Added positive coverage that writable update still works.
  • Added regression coverage proving read-only recall does not refresh last_accessed, with a writable positive control.
  • pytest lib/crewai/tests/memory: 134 passed, 19 skipped.
  • ruff: clean.
  • hermes-gate fast and review: PASS, zero findings.

`Memory.read_only` was enforced only on `remember()` and `remember_many()`.
Two other paths still mutated the backing store:

- `update()` re-embedded the supplied content and wrote the record back.
- `recall()` refreshed `last_accessed` through `touch_records()`, so simply
  reading a read-only memory left a persistent trace.

Both now respect the flag, so a read-only Memory leaves stored records
unchanged. `update()` returns the existing record untouched rather than
raising, matching the silent no-op behaviour of `remember()`. Explicit
deletion through `forget()`/`reset()` is deliberately unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HkDjVYVzHFEj5re9B8JH9p
@coderabbitai

coderabbitai Bot commented Sep 10, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 677ddfd6-88f2-4d8e-9d10-444b70a74690

📥 Commits

Reviewing files that changed from the base of the PR and between a8d330d and 5a6860a.

📒 Files selected for processing (2)
  • lib/crewai/src/crewai/memory/unified_memory.py
  • lib/crewai/tests/memory/test_unified_memory.py

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Memory.read_only now blocks implicit writes from update() and recall(). Documentation describes the behavior, and regression tests cover read-only no-ops plus writable positive controls.

Changes

Read-only memory behavior

Layer / File(s) Summary
Read-only operation guards
lib/crewai/src/crewai/memory/unified_memory.py
update() returns the existing record without changes when read-only. recall() skips access-time refresh. The field documentation describes these rules.
Read-only behavior validation
lib/crewai/tests/memory/test_unified_memory.py
Tests verify read-only update and recall behavior, plus writable update and recall behavior.

Suggested reviewers: joaomdmoura

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 4e7c1

Read-only memory now leaves records and access timestamps unchanged for update and recall operations, while writable behavior remains covered. No merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the two main changes: honoring read_only in update() and preventing recall() access-time writes.
Description check ✅ Passed The description includes the linked issue, change summary, rationale, verification results, and test coverage. It does not include a separate Additional context section, but the required information i…
Linked Issues check ✅ Passed The changes satisfy issue #7368. Read-only update() returns the existing record without mutation, read-only recall() skips access-time persistence, explicit deletion remains unchanged, and regression …
Out of Scope Changes check ✅ Passed The changes are limited to the read_only behavior in Memory, related documentation, and focused regression tests. No unrelated code changes are identified.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 2 files.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Vidit-Ostwal

Copy link
Copy Markdown
Contributor

@lorenzejay Mind taking a look?

@Vidit-Ostwal Vidit-Ostwal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. This correctly makes Memory.read_only prevent update writes and recall access-time writes, with focused regression coverage.

@Vidit-Ostwal
Vidit-Ostwal enabled auto-merge (squash) September 15, 2026 11:15
@Vidit-Ostwal
Vidit-Ostwal merged commit c6ff786 into crewAIInc:main Sep 15, 2026
53 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Memory read_only still persists update and recall access-time writes

2 participants