275 lines
8.5 KiB
Plaintext
275 lines
8.5 KiB
Plaintext
---
|
|
title: Temporal Reasoning
|
|
description: "Use time-aware memory retrieval in Mem0 Platform v3 so searches like 'last week', 'upcoming', and 'right now' return the right memories."
|
|
icon: "clock"
|
|
badge: "v3"
|
|
---
|
|
|
|
Some memories should matter because of **when** they happened, not just because they sound similar. Temporal Reasoning helps Mem0 Platform v3 classify time-aware memories on write and interpret time-aware queries on search.
|
|
|
|
<Info>
|
|
**You'll use this when…**
|
|
- Users ask questions like "what happened last week?" or "what do I have coming up?"
|
|
- Your app stores both past events and future plans for the same person
|
|
- You want time-aware retrieval without building your own date parsing layer
|
|
</Info>
|
|
|
|
<Warning>
|
|
Temporal Reasoning is a **Mem0 Platform v3** feature. It does not apply to OSS memory stores or older Platform endpoints.
|
|
</Warning>
|
|
|
|
## Configure access
|
|
|
|
Confirm your `MEM0_API_KEY` is configured and that you are using the v3 Platform client:
|
|
|
|
```python
|
|
from mem0 import MemoryClient
|
|
|
|
client = MemoryClient(api_key="your-api-key")
|
|
```
|
|
|
|
## How it works
|
|
|
|
Temporal Reasoning has two public-facing parts:
|
|
|
|
- **Write-time enrichment**: when Mem0 stores a memory, it can attach temporal structure such as memory type and date bounds when that information is present in the text.
|
|
- **Search-time interpretation**: when a query includes time language like `last week`, `upcoming`, or `right now`, Mem0 uses the stored temporal fields to return more appropriate results.
|
|
|
|
### Memory types
|
|
|
|
Mem0 normalizes temporal memories into a small set of developer-facing types:
|
|
|
|
| Type | What it represents | Example |
|
|
| --- | --- | --- |
|
|
| `event` | A dated occurrence | "I finished the Q1 review on March 10, 2025." |
|
|
| `plan` | A future commitment or scheduled item | "I have a dentist appointment on March 18, 2025." |
|
|
| `state` | An ongoing fact that can remain true over time | "I am the product lead at Acme Corp." |
|
|
| `relationship` | A durable connection between people or entities | "Priya manages Jordan." |
|
|
| `preference` | A stable preference or habit | "I prefer morning meetings." |
|
|
|
|
On search responses, temporal fields are returned as top-level result attributes when Temporal Reasoning is active. The most useful ones are:
|
|
|
|
- `memory_type`
|
|
- `event_date`
|
|
- `event_start`
|
|
- `event_end`
|
|
- `plan_status`
|
|
- `effective_plan_status`
|
|
- `time_precision`
|
|
- `temporal_surface`
|
|
- `reference_date_used`
|
|
- `score_breakdown.temporal_boost`
|
|
|
|
## Configure it
|
|
|
|
### Default behavior
|
|
|
|
Temporal Reasoning is enabled by default for supported v3 searches and writes.
|
|
|
|
### Per-request override
|
|
|
|
Use `temporal_reasoning=False` when you want a specific call to behave like a normal semantic add or search.
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
client.add(
|
|
[{"role": "user", "content": "Preferred language is English."}],
|
|
user_id="jordan",
|
|
temporal_reasoning=False,
|
|
)
|
|
|
|
results = client.search(
|
|
"preferred language",
|
|
filters={"user_id": "jordan"},
|
|
temporal_reasoning=False,
|
|
)
|
|
```
|
|
|
|
```javascript JavaScript
|
|
await client.add(
|
|
[{ role: "user", content: "Preferred language is English." }],
|
|
{ userId: "jordan", temporalReasoning: false }
|
|
);
|
|
|
|
const results = await client.search("preferred language", {
|
|
filters: { user_id: "jordan" },
|
|
temporalReasoning: false,
|
|
});
|
|
```
|
|
|
|
```bash cURL
|
|
curl -X POST "https://api.mem0.ai/v3/memories/search/" \
|
|
-H "Authorization: Token your-api-key" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"query": "preferred language",
|
|
"filters": { "user_id": "jordan" },
|
|
"temporal_reasoning": false
|
|
}'
|
|
```
|
|
</CodeGroup>
|
|
|
|
### Anchor imports and tests
|
|
|
|
Two fields matter when you want predictable temporal behavior:
|
|
|
|
- `timestamp` on `add()` anchors imported memories to the time they actually happened
|
|
- `reference_date` on `search()` anchors relative queries like `last week` to a known point in time
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
from datetime import datetime, timezone
|
|
|
|
client.add(
|
|
[{"role": "user", "content": "I finished the Q1 review on March 10, 2025."}],
|
|
user_id="jordan",
|
|
timestamp=int(datetime(2025, 3, 10, tzinfo=timezone.utc).timestamp()),
|
|
)
|
|
|
|
results = client.search(
|
|
"what did I do last week?",
|
|
filters={"user_id": "jordan"},
|
|
reference_date="2025-03-21T00:00:00Z",
|
|
)
|
|
```
|
|
|
|
```javascript JavaScript
|
|
await client.add(
|
|
[{ role: "user", content: "I finished the Q1 review on March 10, 2025." }],
|
|
{
|
|
userId: "jordan",
|
|
timestamp: Math.floor(new Date("2025-03-10T00:00:00Z").getTime() / 1000),
|
|
}
|
|
);
|
|
|
|
const results = await client.search("what did I do last week?", {
|
|
filters: { user_id: "jordan" },
|
|
referenceDate: "2025-03-21T00:00:00Z",
|
|
});
|
|
```
|
|
</CodeGroup>
|
|
|
|
<Tip>
|
|
`reference_date` is especially useful for tests, backfills, and cookbook examples because it makes relative phrases reproducible.
|
|
</Tip>
|
|
|
|
## See it in action
|
|
|
|
### Add a few dated memories
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
client.add(
|
|
[{"role": "user", "content": "I finished the Q1 product review on March 10, 2025."}],
|
|
user_id="jordan",
|
|
)
|
|
|
|
client.add(
|
|
[{"role": "user", "content": "I have a dentist appointment on April 18, 2025 at 2 PM."}],
|
|
user_id="jordan",
|
|
)
|
|
|
|
client.add(
|
|
[{"role": "user", "content": "I am the product lead at Acme Corp."}],
|
|
user_id="jordan",
|
|
)
|
|
```
|
|
|
|
```javascript JavaScript
|
|
await client.add(
|
|
[{ role: "user", content: "I finished the Q1 product review on March 10, 2025." }],
|
|
{ userId: "jordan" }
|
|
);
|
|
|
|
await client.add(
|
|
[{ role: "user", content: "I have a dentist appointment on April 18, 2025 at 2 PM." }],
|
|
{ userId: "jordan" }
|
|
);
|
|
|
|
await client.add(
|
|
[{ role: "user", content: "I am the product lead at Acme Corp." }],
|
|
{ userId: "jordan" }
|
|
);
|
|
```
|
|
</CodeGroup>
|
|
|
|
<Note>
|
|
Platform writes are asynchronous. For quick validation, wait briefly before searching or verify the completed event in the dashboard or CLI.
|
|
</Note>
|
|
|
|
### Search with a temporal query
|
|
|
|
<CodeGroup>
|
|
```python Python
|
|
results = client.search(
|
|
"what did I do last week?",
|
|
filters={"user_id": "jordan"},
|
|
reference_date="2025-03-21T00:00:00Z",
|
|
)
|
|
|
|
for item in results["results"]:
|
|
print(item["memory"], item.get("memory_type"), item.get("event_date"))
|
|
```
|
|
|
|
```javascript JavaScript
|
|
const results = await client.search("what did I do last week?", {
|
|
filters: { user_id: "jordan" },
|
|
referenceDate: "2025-03-21T00:00:00Z",
|
|
});
|
|
|
|
results.results.forEach((item) => {
|
|
console.log(item.memory, item.memoryType, item.eventDate);
|
|
});
|
|
```
|
|
</CodeGroup>
|
|
|
|
<Info icon="check">
|
|
Expected behavior: the March 10 review appears as a past `event`, the April 18 appointment does not lead this result set, and the ongoing role at Acme does not crowd out the dated answer.
|
|
</Info>
|
|
|
|
## Supported query patterns
|
|
|
|
<AccordionGroup>
|
|
<Accordion title="Historical questions">
|
|
Examples: `last week`, `last month`, `in March 2025`, `on 2025-03-10`
|
|
</Accordion>
|
|
<Accordion title="Upcoming questions">
|
|
Examples: `upcoming`, `next week`, `tomorrow`, `what do I have coming up?`
|
|
</Accordion>
|
|
<Accordion title="Current-state questions">
|
|
Examples: `right now`, `currently`, `where do I work now?`
|
|
</Accordion>
|
|
<Accordion title="As-of questions">
|
|
Examples: `as of March 2025`, `where was I living as of 2024?`
|
|
</Accordion>
|
|
<Accordion title="Duration questions">
|
|
Examples: `how long have I lived here?`, `since when have I worked there?`
|
|
</Accordion>
|
|
</AccordionGroup>
|
|
|
|
## Verify the feature is working
|
|
|
|
- Run a temporal search and confirm results include top-level fields like `memory_type`, `event_date`, or `effective_plan_status`.
|
|
- Repeat the same query with `temporal_reasoning=False` and confirm ranking changes for time-sensitive prompts.
|
|
- Use `reference_date` in test queries so relative phrases resolve consistently.
|
|
- For backfilled data, confirm imported memories use the expected chronology after you set `timestamp`.
|
|
|
|
## Best practices
|
|
|
|
- Use explicit dates in source conversations when plans or events matter.
|
|
- Pass `timestamp` during historical imports so ingestion time does not become the only time anchor.
|
|
- Keep search scoped with `filters` so time-aware ranking runs inside the right entity boundary.
|
|
- Use `reference_date` in automated tests and reproducible demos.
|
|
- Disable Temporal Reasoning only for clearly timeless lookups such as static profile fields.
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="Memory Timestamps" icon="calendar" href="/platform/features/timestamp">
|
|
Anchor imported memories to when they actually happened.
|
|
</Card>
|
|
<Card title="Answer Time-Aware Questions" icon="book-open" href="/cookbooks/essentials/temporal-memory-assistant">
|
|
Follow the cookbook for an end-to-end temporal retrieval workflow.
|
|
</Card>
|
|
</CardGroup>
|
|
|
|
<Snippet file="get-help.mdx" />
|