[Feature]: Expose record timestamps in retrieval results
Issue Origin
Observed or reproduced in a real environment
Problem Statement
Retrieval clients cannot assess the age of a returned item from the result itself. OpenViking stores created_at and updated_at on indexed context records, but the shared retrieval conversion drops both values before REST, SDK, and MCP output.
This matters when old and corrected facts both match a query. External agent-memory users report this failure mode and state that a visible update time helps the caller distinguish stale content:
- https://www.reddit.com/r/AI_Agents/comments/1uxwp0i/comment/oxw2bno/
- https://www.reddit.com/r/AI_Agents/comments/1uxwp0i/comment/oxut97n/
- https://www.reddit.com/r/AI_Agents/comments/1uxwp0i/comment/oxv44pr/
Current source inspection and a focused fixture confirm the gap. A record with both timestamps becomes a MatchedContext with neither timestamp. FindResult.to_dict() then cannot return them. Standard vector retrieval already obtains updated_at for optional hotness scoring. Filter-only retrieval obtains both fields.
stat(uri) is not equivalent. It requires a later request for each item, returns current filesystem modTime rather than the indexed-result values, cannot return a preserved vector-record created_at, and is not a general MCP tool. A later lookup can also race with a write or reindex.
Proposed Solution
Add an opt-in include_timestamps option to list-mode find and search. When it is true, include the existing indexed created_at and updated_at values on each result item. Keep the default false.
The shared retrieval model must carry the two values so semantic and filter-only retrieval produce the same contract. Standard retrieval must request created_at in addition to its existing updated_at field. REST, supported SDKs, and MCP should expose the same option.
Do not change ranking, filtering, storage, update behavior, result order, or context-assembly mode. Do not add expiry, freshness ranking, contradiction resolution, automatic truth selection, or new memory lifecycle semantics.
Alternatives Considered
- Reuse
include_provenance: rejected because it already means query execution traces and searched directories. - Call
stat(uri)for every result: rejected because it adds N requests and does not return the exact indexed-result timestamp pair. - Return timestamps by default: rejected because the opt-in form preserves the current response shape.
Feature Area
Retrieval/Search
Use Case
An agent retrieves two facts about the same subject. The caller requests timestamps and compares the returned evidence age before it chooses which item to inspect or use. The caller remains responsible for policy. OpenViking only exposes existing record metadata.
Success criteria:
- With
include_timestamps=true, every result that has stored timestamps returns their exact values. - Semantic and filter-only retrieval preserve the same values.
- Default output remains unchanged.
- Ranking and result order remain unchanged.
- REST, supported SDKs, and MCP use one consistent option.
Example API (Optional)
result = client.find(
"current plan price",
options={"include_timestamps": True},
)
# result["resources"][0]
{
"uri": "viking://resources/plans.md",
"abstract": "...",
"score": 0.91,
"created_at": "2026-08-01T09:00:00.000Z",
"updated_at": "2026-09-15T11:30:00.000Z",
}Additional Context
Searches of current source, upstream branches, issues, discussions, and open, draft, merged, and closed PRs found no equivalent implementation. PR #1429 adds time filters, and PR #852 adds query-path provenance. Neither returns record timestamps with result items.
Contribution
- I am willing to contribute to implementing this feature
Source: volcengine/OpenViking