Skip to content

fix(memory): handle timezone-aware created_at in compute_composite_score#6161

Open
i-anubhav-anand wants to merge 1 commit into
crewAIInc:mainfrom
i-anubhav-anand:fix/memory-composite-score-tz-aware
Open

fix(memory): handle timezone-aware created_at in compute_composite_score#6161
i-anubhav-anand wants to merge 1 commit into
crewAIInc:mainfrom
i-anubhav-anand:fix/memory-composite-score-tz-aware

Conversation

@i-anubhav-anand

@i-anubhav-anand i-anubhav-anand commented Jun 14, 2026

Copy link
Copy Markdown

Summary

compute_composite_score (crewai.memory.types) computed the recency age as:

age_seconds = (datetime.utcnow() - record.created_at).total_seconds()

datetime.utcnow() returns a naive datetime. When a MemoryRecord is created with a timezone-aware created_at — e.g. datetime.now(timezone.utc), the modern/recommended idiom — this subtraction raises:

TypeError: can't subtract offset-naive and offset-aware datetimes

Reproduction

from datetime import datetime, timezone
from crewai.memory.types import MemoryRecord, MemoryConfig, compute_composite_score

record = MemoryRecord(content="hi", created_at=datetime.now(timezone.utc))
compute_composite_score(record, semantic_score=0.8, config=MemoryConfig())
# TypeError: can't subtract offset-naive and offset-aware datetimes

Fix

Use a timezone-aware now and treat a naive created_at as UTC before subtracting, so both the (naive) default-factory value and aware values work. This also removes the deprecated datetime.utcnow() call from the scoring path (utcnow() is deprecated as of Python 3.12).

Scoped to the crash. The created_at/last_accessed default factories still use datetime.utcnow (changing those would flip the default to aware and alter serialization) — happy to follow up on the broader utcnow() deprecation sweep separately if desired.

Testing

  • Added tests/memory/test_types.py covering aware and naive created_at. The aware case fails before this change (TypeError) and passes after.
  • uv run pytest tests/memory/test_types.py2 passed.
  • ruff check / ruff format --check clean on touched files.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed timezone handling in memory age calculations to prevent errors when processing different datetime formats.
  • Tests

    • Added test coverage for memory scoring with various timezone configurations.

The recency age was computed as `datetime.utcnow() - record.created_at`.
`utcnow()` returns a naive datetime, so when a MemoryRecord is created with
a timezone-aware `created_at` (e.g. `datetime.now(timezone.utc)`, the modern
idiom) the subtraction raises `TypeError: can't subtract offset-naive and
offset-aware datetimes`.

Use a timezone-aware now and treat a naive `created_at` as UTC before
subtracting, so both the (naive) default factory and aware values work. This
also drops the deprecated `datetime.utcnow()` call from the scoring path.

Adds tests covering aware and naive `created_at`.
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

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: 0d668700-5e91-40c9-8945-2e06c7b69133

📥 Commits

Reviewing files that changed from the base of the PR and between bb477f8 and 32f0112.

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

📝 Walkthrough

Walkthrough

compute_composite_score is updated to replace datetime.utcnow() with datetime.now(timezone.utc) and to coerce naive record.created_at values to UTC-aware before computing age_seconds. A new test file validates bounded score output and "semantic" in reasons for both timezone-aware and naive created_at inputs.

Changes

Timezone-safe memory age calculation

Layer / File(s) Summary
Timezone-safe age_seconds computation and tests
lib/crewai/src/crewai/memory/types.py, lib/crewai/tests/memory/test_types.py
timezone is added to the datetime import; compute_composite_score uses datetime.now(timezone.utc) and replaces naive subtraction with UTC-aware normalization of record.created_at; two new tests assert score bounds and "semantic" in reasons for both aware and naive created_at values.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐇 No more TypeError in the warren tonight,
Naive and aware clocks now set aright.
UTC timestamps hop into place,
Age seconds computed with timezone grace.
The score stays bounded, the reasons ring true —
A timezone-safe fix from me to you! 🕰️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main fix: handling timezone-aware datetime values in the compute_composite_score function, which directly addresses the TypeError bug detailed in the PR objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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