diff --git a/python/packages/kagent-crewai/src/kagent/crewai/_memory.py b/python/packages/kagent-crewai/src/kagent/crewai/_memory.py index aef7d1628..0b0ce614d 100644 --- a/python/packages/kagent-crewai/src/kagent/crewai/_memory.py +++ b/python/packages/kagent-crewai/src/kagent/crewai/_memory.py @@ -26,7 +26,7 @@ def __init__(self, thread_id: str, user_id: str, base_url: str): self.user_id = user_id self.base_url = base_url - def save(self, task_description: str, metadata: dict, timestamp: str, score: float) -> None: + def save(self, task_description: str, metadata: dict, datetime: str, score: float) -> None: """ Saves a memory item to the Kagent backend. The agent_id is expected to be in the metadata. @@ -39,7 +39,7 @@ def save(self, task_description: str, metadata: dict, timestamp: str, score: flo "task_description": task_description, "score": score, "metadata": metadata, - "datetime": timestamp, + "datetime": datetime, }, ) diff --git a/python/packages/kagent-crewai/tests/conftest.py b/python/packages/kagent-crewai/tests/conftest.py new file mode 100644 index 000000000..1459449f3 --- /dev/null +++ b/python/packages/kagent-crewai/tests/conftest.py @@ -0,0 +1,30 @@ +import os + +_DEFAULTS = { + "KAGENT_URL": "http://localhost:8080", + "KAGENT_NAME": "test-agent", + "KAGENT_NAMESPACE": "default", +} + +_ORIGINAL_ENV: dict[str, str | None] = {} + + +def pytest_configure(config): + # The kagent.crewai package imports KAgentApp at module load, which constructs a + # KAgentConfig and requires these environment variables to be present. Set safe + # defaults so the package can be imported in unit tests without a running backend. + for key, value in _DEFAULTS.items(): + if key in os.environ: + _ORIGINAL_ENV[key] = os.environ[key] + else: + _ORIGINAL_ENV[key] = None + os.environ[key] = value + + +def pytest_unconfigure(config): + # Restore environment so these defaults don't leak into other test suites. + for key, original in _ORIGINAL_ENV.items(): + if original is None: + os.environ.pop(key, None) + else: + os.environ[key] = original diff --git a/python/packages/kagent-crewai/tests/test_memory.py b/python/packages/kagent-crewai/tests/test_memory.py new file mode 100644 index 000000000..57db578aa --- /dev/null +++ b/python/packages/kagent-crewai/tests/test_memory.py @@ -0,0 +1,54 @@ +import inspect +from unittest.mock import MagicMock, patch + +from crewai.memory.long_term.long_term_memory import LongTermMemory +from crewai.memory.long_term.long_term_memory_item import LongTermMemoryItem +from crewai.memory.storage.ltm_sqlite_storage import LTMSQLiteStorage + +from kagent.crewai._memory import KagentMemoryStorage + + +def test_save_signature_matches_crewai_storage_contract(): + """KagentMemoryStorage.save must accept the same keyword arguments CrewAI's + LongTermMemory passes to its storage. CrewAI calls storage.save() with + datetime= as a keyword (see LongTermMemory.save), and the reference + LTMSQLiteStorage.save names that parameter 'datetime'.""" + reference_params = list(inspect.signature(LTMSQLiteStorage.save).parameters) + kagent_params = list(inspect.signature(KagentMemoryStorage.save).parameters) + assert kagent_params == reference_params + + +def test_long_term_memory_save_posts_datetime(): + """A memory-enabled CrewAI crew wires KagentMemoryStorage as its + LongTermMemory backend. Saving must not raise and must forward the item's + datetime to the Kagent backend.""" + storage = KagentMemoryStorage( + thread_id="thread-1", + user_id="user-1", + base_url="http://kagent.test", + ) + long_term_memory = LongTermMemory(storage) + item = LongTermMemoryItem( + agent="researcher", + task="summarize the report", + expected_output="a summary", + datetime="2020-01-01T00:00:00", + quality=0.9, + metadata={"quality": 0.9}, + ) + + with patch("kagent.crewai._memory.httpx.Client") as mock_client_cls: + mock_client = MagicMock() + mock_client_cls.return_value.__enter__.return_value = mock_client + mock_response = MagicMock() + mock_response.raise_for_status.return_value = None + mock_client.post.return_value = mock_response + + long_term_memory.save(item) + + mock_client.post.assert_called_once() + _, kwargs = mock_client.post.call_args + memory_data = kwargs["json"]["memory_data"] + assert memory_data["datetime"] == "2020-01-01T00:00:00" + assert memory_data["task_description"] == "summarize the report" + assert memory_data["score"] == 0.9