Temporal Reasoning
Temporal Reasoning enables WASP to understand how things have changed over time — not just what the current state is, but how it got there and what trends suggest about the future.
Overview
The TemporalReasoner (src/memory/temporal.py) provides:
- Extraction — rule-based extraction of temporal data from conversation text
- Storage — writes to
world_timelinefor historical tracking - Insights — generates
[TEMPORAL INSIGHTS]block for the system prompt - Change detection — identifies when entities have meaningfully changed state
Temporal Extraction
After every message, extract_from_text() scans for:
Price Mentions
"BTC went up to $68,000 today"
→ entity=BTC, value=68000, observation_type=price
State Changes
"I finished the project yesterday"
→ entity=project, state=completed, observation_type=state
Relative Time References
"last week the server was at 80% CPU"
→ entity=server_cpu, value=80%, observation_type=metric, timeref=last_week
Contamination Guards
The extractor uses _CONTAMINATION_GUARDS — a list of patterns that indicate garbage text which should not be extracted:
_CONTAMINATION_GUARDS = [
r"^\s*\"", # Starts with quote (JSON artifact)
r"lament.*inconvenientes", # Error message artifacts
r"technically.*problems", # Error message artifacts
...
]
Any text matching a guard is skipped entirely.
Context Injection
The _temporal_insights() function in build_context():
- Reads recent
world_timelineentries (last 24 hours) - Groups by entity
- Generates trend descriptions
[TEMPORAL INSIGHTS]
BTC: $67,663 (stable, -0.99% from yesterday's $68,337)
ETH: $1,950 (stable, -1.68% from yesterday's $1,983)
Last observed: 2 hours ago
Token efficiency: When the [TEMPORAL INSIGHTS] block is present, the world_model_block (which covers the same entities) is suppressed to avoid duplication.
Get Entity History
from src.memory.temporal import get_entity_history
history = await get_entity_history(entity="BTC", hours=24, session=session)
# Returns list of (timestamp, value) pairs
Detect Change
from src.memory.temporal import detect_change
change = await detect_change(entity="BTC", session=session)
# Returns: {"changed": True, "from": 68000, "to": 67663, "pct": -0.99, "direction": "down"}
Configuration
| Setting | Default | Description |
|---|---|---|
TEMPORAL_REASONING_ENABLED | true | Enable/disable temporal insights |
TEMPORAL_REASONING_MAX_INSIGHTS | 5 | Max entities to include in insights block |
Integration with Perception
The BackgroundPerceptionJob uses temporal reasoning to decide when to notify:
change = await detect_change(entity=asset, session=session)
if abs(change["pct"]) > 4.0:
# Ask LLM: is this notable enough to notify?
notable = await assess_notability(change, context)
if notable:
await send_telegram_alert(...)
Integration with Dream Mode
During Dream Mode, DreamJob prefetches prices for all KG crypto assets and stores them in world_timeline with source=dream_prefetch. This ensures temporal data is available even if the user hasn't mentioned prices recently.
Database Schema
-- world_timeline (time series)
CREATE TABLE world_timeline (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
entity VARCHAR(255) NOT NULL,
value TEXT,
observation_type VARCHAR(50), -- price, state, metric, mention
source VARCHAR(100), -- conversation, dream_prefetch, perception_job
chat_id VARCHAR(255),
timestamp TIMESTAMPTZ DEFAULT NOW()
);
-- entity_states (current state, aggregated)
CREATE TABLE entity_states (
entity VARCHAR(255) PRIMARY KEY,
current_value TEXT,
trend VARCHAR(20), -- rising, falling, stable, unknown
change_pct FLOAT,
updated_at TIMESTAMPTZ DEFAULT NOW()
);
Querying History
# Full history for BTC
docker exec agent-postgres psql -U agent -d agent -c "
SELECT entity, value, observation_type, source, timestamp
FROM world_timeline
WHERE entity = 'BTC'
ORDER BY timestamp DESC
LIMIT 50;
"
# All current entity states
docker exec agent-postgres psql -U agent -d agent -c "
SELECT * FROM entity_states ORDER BY updated_at DESC;
"