Skip to content

fix: replace deprecated datetime.utcnow() across the memory subsystem#5970

Open
kratos0718 wants to merge 1 commit into
crewAIInc:mainfrom
kratos0718:fix/replace-deprecated-datetime-utcnow-in-memory
Open

fix: replace deprecated datetime.utcnow() across the memory subsystem#5970
kratos0718 wants to merge 1 commit into
crewAIInc:mainfrom
kratos0718:fix/replace-deprecated-datetime-utcnow-in-memory

Conversation

@kratos0718
Copy link
Copy Markdown

@kratos0718 kratos0718 commented May 29, 2026

Summary

datetime.utcnow() is deprecated since Python 3.12 and is scheduled for removal in Python 3.14. crewAI's requires-python is >=3.10, <3.14, so users on the currently-supported 3.12 and 3.13 see a DeprecationWarning on every memory write/read, and the project cannot bump its upper bound to include 3.14 without first removing these calls.

This PR replaces all 9 call sites across 4 files in the memory subsystem.

Why the chosen replacement preserves behavior exactly

I used datetime.now(timezone.utc).replace(tzinfo=None) rather than the more modern datetime.now(timezone.utc) because:

  1. Persisted data compatibility. MemoryRecord.created_at and last_accessed may already be on disk in users' LanceDB tables as naive datetimes via the existing default_factory=datetime.utcnow. Switching to aware datetimes would either:

    • Break compute_composite_score (naive - aware raises TypeError: can't subtract offset-naive and offset-aware datetimes), or
    • Silently change the on-disk .isoformat() representation from 2026-05-29T05:00:00 to 2026-05-29T05:00:00+00:00, which can affect downstream parsers.
  2. Goal of the patch. Remove the deprecation without touching any user-visible semantics.

A follow-up could migrate the whole memory module to timezone-aware datetimes, but that's a separate, behavior-changing PR.

Files changed

File Call sites What
memory/types.py 3 2 default_factory on MemoryRecord, 1 in compute_composite_score's recency decay
memory/storage/lancedb_storage.py 4 created_at/last_accessed writes, _parse_dt fallback, batch update timestamp
memory/encoding_flow.py 1 EncodingFlow._apply_actions timestamp
memory/unified_memory.py 1 Memory.update_record timestamp

Each file's from datetime import datetime was extended to from datetime import datetime, timezone.

Verification

  • No semantic change: every call still returns a naive UTC datetime, identical to what datetime.utcnow() previously returned.
  • No new dependencies.
  • No test changes required — existing memory tests continue to pass against this drop-in replacement.

Summary by CodeRabbit

  • Refactor
    • Updated internal timestamp handling in the memory module to use standardized UTC datetime generation across all memory operations.

Review Change Stack

`datetime.utcnow()` is deprecated since Python 3.12 (per
[official docs](https://docs.python.org/3/library/datetime.html#datetime.datetime.utcnow))
and is scheduled for removal in Python 3.14. crewAI's `requires-python`
range is `>=3.10, <3.14`, so users on supported 3.12 and 3.13 currently
see a `DeprecationWarning` on every memory write/read, and the project
cannot bump its upper bound to include 3.14 without first removing
these calls.

This PR replaces all 9 call sites across 4 files in the memory
subsystem with `datetime.now(timezone.utc).replace(tzinfo=None)`, which
is the exact behavioral equivalent (current UTC time as a timezone-naive
datetime). I deliberately preserved naive datetimes rather than moving
to timezone-aware ones because:

  1. `MemoryRecord.created_at` and `last_accessed` may already be
     persisted as naive datetimes in users' LanceDB tables; switching
     to aware would either break subtractions in `compute_composite_score`
     (`naive - aware` raises `TypeError`) or silently change the on-disk
     `.isoformat()` representation (`...` vs `...+00:00`).

  2. The goal is to remove the deprecation without changing any
     user-visible semantics.

## Files changed

| File | Call sites |
|------|-----------|
| `memory/types.py` | 3 — 2 `default_factory` in `MemoryRecord`, 1 in `compute_composite_score` |
| `memory/storage/lancedb_storage.py` | 4 — `created_at`/`last_accessed` writes, `_parse_dt` fallback, batch update timestamp |
| `memory/encoding_flow.py` | 1 — `EncodingFlow` apply-actions timestamp |
| `memory/unified_memory.py` | 1 — `Memory` record update timestamp |

Each file's `from datetime import datetime` was extended to
`from datetime import datetime, timezone`.

## Behavior

Zero behavior change. Existing tests that compare or serialize these
datetimes will continue to pass.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 96ef7da9-d2fd-44a8-952b-6083e9ac3793

📥 Commits

Reviewing files that changed from the base of the PR and between fca21b1 and 7324392.

📒 Files selected for processing (4)
  • lib/crewai/src/crewai/memory/encoding_flow.py
  • lib/crewai/src/crewai/memory/storage/lancedb_storage.py
  • lib/crewai/src/crewai/memory/types.py
  • lib/crewai/src/crewai/memory/unified_memory.py

📝 Walkthrough

Walkthrough

The pull request replaces all uses of deprecated datetime.utcnow() with datetime.now(timezone.utc).replace(tzinfo=None) across the memory module. Changes span memory type definitions, storage operations, and execution paths, importing timezone from the datetime module to enable timezone-aware UTC timestamp construction.

Changes

Memory Timestamp Standardization

Layer / File(s) Summary
Memory record types and scoring
lib/crewai/src/crewai/memory/types.py
Import timezone and update MemoryRecord.created_at and last_accessed field defaults and compute_composite_score recency calculation to use datetime.now(timezone.utc).replace(tzinfo=None) instead of datetime.utcnow.
Storage implementation timestamps
lib/crewai/src/crewai/memory/storage/lancedb_storage.py
Import timezone and update schema placeholder record initialization, _parse_dt fallback parsing, and touch_records methods to generate timestamps using timezone-aware UTC.
Memory operation timestamps
lib/crewai/src/crewai/memory/encoding_flow.py, lib/crewai/src/crewai/memory/unified_memory.py
Import timezone and update execute_plans and Memory.update methods to compute last_accessed timestamps using datetime.now(timezone.utc).replace(tzinfo=None).

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Clocks now tick with timezone flair,
UTC aware, beyond compare!
No more .utcnow() in the night,
Each timestamp shines with awareness bright!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: replacing deprecated datetime.utcnow() calls across the memory subsystem with the recommended alternative.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 and usage tips.

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.

1 participant