time-aware-retrieval
Temporal awareness in RAG. Recency bias weighting, exponential decay scoring, time-range filtering, LLM-based date extraction ("last quarter", "yesterday"), temporal knowledge graphs, freshness vs authority tradeoff, event-based retrieval, timestamp metadata, differential reindexing of old vs fresh docs. USE WHEN: user mentions "time-aware RAG", "recency bias", "temporal retrieval", "freshness", "date filter", "temporal knowledge graph", "exponential decay" DO NOT USE FOR: static metadata filters generally - use `self-querying-retriever`; CDC for ingestion - use `cdc-streaming-ingestion`; evaluation of time-sensitive answers - use `rag-evaluation`
What this skill does
# Time-Aware Retrieval
## Why It Matters
"What is our refund policy?" should return the current policy, not the 2019 version. Pure semantic similarity often prefers older verbose documents that match more query terms. Time awareness corrects this.
Two failure modes to prevent:
1. **Stale wins**: old doc ranks above newer authoritative doc because it's more verbose.
2. **Fresh-but-wrong**: auto-generated recent doc outranks the authoritative but older source of truth.
## Approaches
| Approach | Needs | Strength | Weakness |
|---|---|---|---|
| Hard time filter | Date in query | Exact scoping | Fails for vague time |
| Recency decay | Timestamp metadata | Smooth, always applies | Can bury important old docs |
| LLM date extraction | LLM call | Handles "last quarter" | Latency + cost |
| Temporal KG | Entities with time edges | Multi-step time reasoning | Complex to build |
| Authority + recency blend | Authority score | Balances fresh vs canonical | Authority signal is hard |
## Timestamp Metadata
Every chunk needs at least:
- `created_at` — original publication time.
- `updated_at` — last content-significant edit.
- `valid_from`, `valid_to` — if the fact has explicit validity.
```python
from pydantic import BaseModel
from datetime import datetime
class ChunkMetadata(BaseModel):
chunk_id: str
doc_id: str
created_at: datetime
updated_at: datetime
valid_from: datetime | None = None
valid_to: datetime | None = None
source_authority: float = 0.5 # 0-1; 1.0 = official/canonical
```
## Exponential Decay Scoring
```python
import math
from datetime import datetime
HALF_LIFE_DAYS = 180
def recency_weight(updated_at: datetime, now: datetime | None = None) -> float:
now = now or datetime.utcnow()
age_days = (now - updated_at).total_seconds() / 86400
return 0.5 ** (age_days / HALF_LIFE_DAYS)
def blended_score(semantic_score: float, meta: ChunkMetadata, alpha: float = 0.8) -> float:
return alpha * semantic_score + (1 - alpha) * recency_weight(meta.updated_at)
```
Half-life by domain:
- News: 7-30 days
- Software docs: 180 days
- Legal / regulations: 5-10 years
- Medical guidelines: 3-5 years
- Internal wiki: 365 days
Tune with the eval set; do not guess.
## Authority-Weighted Recency
Pure recency punishes canonical sources (e.g., the constitution). Blend with authority.
```python
def time_authority_score(semantic: float, meta: ChunkMetadata,
w_sem: float = 0.6, w_rec: float = 0.2, w_auth: float = 0.2) -> float:
return (w_sem * semantic
+ w_rec * recency_weight(meta.updated_at)
+ w_auth * meta.source_authority)
```
Chunks from `/legal/policies/` get `source_authority=1.0`; chunks from community posts get 0.3.
## LLM Date Extraction
```python
from pydantic import BaseModel, Field
from typing import Literal
from datetime import datetime, timedelta
from langchain_anthropic import ChatAnthropic
class DateRange(BaseModel):
has_time_filter: bool
start: datetime | None = Field(None, description="ISO 8601 start")
end: datetime | None = Field(None, description="ISO 8601 end")
relative_hint: Literal["strict", "soft"] | None = Field(
"soft", description="strict = only these dates; soft = prefer these dates"
)
llm = ChatAnthropic(model="claude-haiku-4-5-20250929", temperature=0).with_structured_output(DateRange)
def extract_time(query: str, today: datetime) -> DateRange:
return llm.invoke(
f"Today is {today.isoformat()}. Extract any time filter from the query. "
f"Return has_time_filter=false if no time reference.\n\nQuery: {query}"
)
```
Examples:
- "refund policy" -> `has_time_filter=False`
- "revenue last quarter" -> `has_time_filter=True`, start/end of Q3 2025
- "what changed since January" -> `has_time_filter=True`, start=2025-01-01, end=today, `soft`
Soft hints feed the recency decay; strict hints become hard filters.
## Query Pipeline
```python
def time_aware_retrieve(query: str, top_k: int = 10):
now = datetime.utcnow()
dr = extract_time(query, now)
candidates = vstore.similarity_search(query, k=100,
filter=build_filter(dr) if dr.has_time_filter and dr.relative_hint == "strict" else None)
scored = []
for d in candidates:
meta = ChunkMetadata(**d.metadata)
base_score = d.metadata["score"]
score = time_authority_score(base_score, meta)
if dr.has_time_filter and dr.relative_hint == "soft":
in_range = (dr.start or datetime.min) <= meta.updated_at <= (dr.end or datetime.max)
score *= 1.2 if in_range else 0.9
scored.append((d, score))
scored.sort(key=lambda x: -x[1])
return [d for d, _ in scored[:top_k]]
def build_filter(dr: DateRange) -> dict:
f = {}
if dr.start: f["updated_at"] = {"$gte": dr.start.isoformat()}
if dr.end: f.setdefault("updated_at", {})["$lte"] = dr.end.isoformat()
return f
```
## Valid-From / Valid-To (versioned facts)
When a fact has explicit validity (policy versions, tax rates, product specs), treat retrieval as time travel.
```python
def facts_valid_at(t: datetime, candidates):
return [d for d in candidates
if (d.metadata.get("valid_from") or datetime.min) <= t
<= (d.metadata.get("valid_to") or datetime.max)]
```
"What was our refund policy on 2024-03-15?" -> `facts_valid_at(2024-03-15)` returns only the then-live version.
## Temporal Knowledge Graph
For facts that evolve (employment, funding, releases), a temporal KG allows reasoning over changes.
```cypher
// Neo4j temporal edge
MERGE (p:Person {name: $name})
MERGE (c:Company {name: $company})
CREATE (p)-[r:WORKED_AT {from: date($from), to: date($to)}]->(c)
```
Query: "Who worked at Acme in 2023?"
```cypher
MATCH (p:Person)-[r:WORKED_AT]->(c:Company {name: 'Acme'})
WHERE r.from <= date('2023-12-31') AND (r.to >= date('2023-01-01') OR r.to IS NULL)
RETURN p.name
```
Zep and Graphiti expose this pattern as a service; they bi-temporal track `valid_time` (when it was true) and `transaction_time` (when we knew it).
## Event-Based Retrieval
Some queries are naturally about events ("the 2024 data breach"). Index events with:
- `event_time` — when the event occurred.
- `event_type` — category.
- `entities_involved` — for filtering/joining.
```python
def event_retrieve(query: str, event_type: str | None = None, before: datetime | None = None):
f = {}
if event_type: f["event_type"] = event_type
if before: f["event_time"] = {"$lte": before.isoformat()}
return vstore.similarity_search(query, k=10, filter=f)
```
## Differential Reindexing
Old docs rarely change; fresh docs change often. Reindexing is expensive — prioritize.
```python
def should_reindex(meta: ChunkMetadata) -> bool:
if (datetime.utcnow() - meta.updated_at).days < 7:
return True # fresh content changes often
if (datetime.utcnow() - meta.updated_at).days < 90:
return meta.source_authority >= 0.7 # canonical sources still matter
return False # cold docs; index only on content hash change
```
Combine with content hashes (see `ingestion-orchestration`): only re-embed when the content hash changed AND `should_reindex` is true.
## Freshness in Evaluation
Include time-sensitive questions in your eval set with ground truth valid at eval time.
```python
# eval_set.jsonl
{"q": "current refund window", "ground_truth_valid_at": "2025-04-15",
"expected_answer": "30 days", "expected_chunks": ["policy_v7"]}
{"q": "refund window in 2020", "ground_truth_valid_at": "2020-06-01",
"expected_answer": "14 days", "expected_chunks": ["policy_v3"]}
```
## Anti-Patterns
| Anti-Pattern | Fix |
|---|---|
| No timestamp metadata at all | Every chunk gets `created_at` and `updated_at` |
| Same half-life for all domains | Tune by content type |
| Pure recency without authority | Canonical docs get buried; blend |
| Strict filter with no fallback | Empty result when nothing in range; fallRelated in AI Agents
skill-development
IncludedComprehensive meta-skill for creating, managing, validating, auditing, and distributing Claude Code skills and slash commands (unified in v2.1.3+). Provides skill templates, creation workflows, validation patterns, audit checklists, naming conventions, YAML frontmatter guidance, progressive disclosure examples, and best practices lookup. Use when creating new skills, validating existing skills, auditing skill quality, understanding skill architecture, needing skill templates, learning about YAML frontmatter requirements, progressive disclosure patterns, tool restrictions (allowed-tools), skill composition, skill naming conventions, troubleshooting skill activation issues, creating custom slash commands, configuring command frontmatter, using command arguments ($ARGUMENTS, $1, $2), bash execution in commands, file references in commands, command namespacing, plugin commands, MCP slash commands, Skill tool configuration, or deciding between skills vs slash commands. Delegates to docs-management skill for official documentation.
reprompter
IncludedTransform messy prompts into well-structured, effective prompts — single or multi-agent. Use when: "reprompt", "reprompt this", "clean up this prompt", "structure my prompt", rough text needing XML tags and best practices, "reprompter teams", "repromptception", "run with quality", "smart run", "smart agents", multi-agent tasks, audits, parallel work, anything going to agent teams. Don't use when: simple Q&A, pure chat, immediate execution-only tasks. See "Don't Use When" section for details. Outputs: Structured XML/Markdown prompt, quality score (before/after), optional team brief + per-agent sub-prompts, agent team output files. Success criteria: Single mode quality score ≥ 7/10; Repromptception per-agent prompt quality score 8+/10; all required sections present, actionable and specific.
adaptive-compaction
IncludedAdaptive add-on policy and recovery layer that decides WHEN to compact, prune, snapshot, or fork -- replacing fixed-percent auto-compaction across Claude Code, Codex, and MCP-capable hosts. Trigger on auto-compact timing or damage: "when should I compact", "is it safe to compact now or start a fresh session", "auto-compact fires too early/mid-task", "switching to an unrelated task but the window still has space", "context rot", "answers get worse the longer the session runs", "the agent forgot the plan or my decisions after it summarized", "add a layer on top that manages context without changing the agent", raising autoCompactWindow to give the policy room, or installing/tuning a cross-tool compaction policy or PreCompact hook -- even when "compaction" is never said but the problem is context-window pressure or post-summarization memory loss. Do NOT use to summarize a conversation, build RAG, write a summarization prompt (decides WHEN not HOW), or answer max-context-length trivia.
agent-skill-creator
IncludedCreate cross-platform agent skills from workflow descriptions. Activates when users ask to create an agent, automate a repetitive workflow, create a custom skill, or need advanced agent creation. Triggers on phrases like create agent for, automate workflow, create skill for, every day I have to, daily I need to, turn process into agent, need to automate, create a cross-platform skill, validate this skill, export this skill, migrate this skill. Supports single skills, multi-agent suites, transcript processing, template-based creation, interactive configuration, cross-platform export, and spec validation.
llm-wiki
IncludedUse when building or maintaining a persistent personal knowledge base (second brain) in Obsidian where an LLM incrementally ingests sources, updates entity/concept pages, maintains cross-references, and keeps a synthesis current. Triggers include "second brain", "Obsidian wiki", "personal knowledge management", "ingest this paper/article/book", "build a research wiki", "compound knowledge", "Memex", or whenever the user wants knowledge to accumulate across sessions instead of being re-derived by RAG on every query.
skill-master
IncludedAgent Skills authoring, evaluation, and optimization. Create, edit, validate, benchmark, and improve skills following the agentskills.io specification. Use when designing SKILL.md files, structuring skill folders (references, scripts, assets), ingesting external documentation into skills, running trigger evals, benchmarking skill quality, optimizing descriptions, or performing blind A/B comparisons. Keywords: agentskills.io, SKILL.md, skill authoring, eval, benchmark, trigger optimization.