This plan outlines the design and integration of temporal anchoring, on-demand web search grounding, and background temporal reflection beats to improve SyntH's awareness of the present.
[User Input / Background Trigger]
│
▼
┌───────────────────┐
│ Retrieval Phase │ ──► (Pulls from Postgres + pgvector)
└───────────────────┘
│
▼
┌───────────────────────────────┐
│ Context Assembly Pipeline │ ◄── [Reality Anchor Injection]
│ (core/prompt_engine.py) │
└───────────────────────────────┘
│
▼
┌───────────────────┐
│ Cortex Engine │ ◄── [Search Tooling]
│ (Gemini REST/ │ ├── Native Gemini Google Search
│ Web Search) │ └── Tavily / DuckDuckGo fallback
└───────────────────┘
│
▼
[Synth Response]
Objective: Force the LLM to calculate all relative time references (e.g., "yesterday", "next week", "two months ago") against the absolute present date, preventing her from defaulting to a pre-cutoff baseline (e.g., 2023 or 2024).
- Context Construction: Located in
_build_context_summary()in prompt_engine.py. - Time Clock Helper:
get_local_time_fields()in time_zone_utils.py converts UTC time to local time (respecting user session overrides) and has already been extended to return"season"(e.g.,"Late Spring") and"day_of_week"(e.g.,"Tuesday"). - Instruction Rules:
load_json_instructions()contains the minified instructions, andload_unminified_chat_instruction()contains unminified instructions. We must refine theTIME AUTHORITYrule to use the anchor instead of casually volunteering raw date quotes in replies.
- Context Summary Refactor:
In
_build_context_summary()(prompt_engine.py), replace the old[Ambient runtime context]block with an always-on[SYSTEM: REALITY ANCHOR]block:[SYSTEM: REALITY ANCHOR] - Current Date: Tuesday, May 26, 2026 (constructed from day_of_week + formatted date) - Current Time: 2:26 PM (formatted 12-hour AM/PM from local time) - Season: Late Spring - Current Location: Ljubljana, Slovenia (or fallback location) - Temporal Delta: It is now 2026. It has been approximately 2-3 years since your primary core baseline training knowledge cutoff (early 2023 / mid-2024 depending on the model). Adjust your perspective on tools, software versions, and global releases to reflect this passage of time naturally.
- Retrieve Extended Fields:
Update
build_prompt_request(prompt_engine.py) to pull"season"and"day_of_week"fromlocal_time_fieldsand populatecontext_sectionwith them. - Instruction Refinement:
Refactor
TIME AUTHORITYandRUNTIME STYLEinstructions inload_json_instructions()andload_unminified_chat_instruction()to refer to[SYSTEM: REALITY ANCHOR]. Instruct the LLM to use it for relative time calculations but strictly avoid quoting dates, the year 2026, or timestamps verbatim unless explicitly requested by the user.
Objective: Provide a mechanism to execute web searches when the Synth encounters a concept she lacks memory of (stale knowledge).
- Web Search Plugin:
Create a new plugin web_search_plugin.py registering the action
search_current_knowledge.- Tavily Integration: If
TAVILY_API_KEYis set in configuration, query Tavily REST API (https://api.tavily.com/search). - DuckDuckGo Scraper (Fallback): If no API key is present, scrape DuckDuckGo's HTML page (
https://html.duckduckgo.com/html/?q=...) usingrequestsandBeautifulSoup. Run the HTTP calls inasyncio.to_threadto prevent blocking the event loop. Parse the top 3-5 snippet results. - Loop Prevention: Skip calling
request_llm_deliveryif the current context indicates the engine is already indeliverymode.
- Tavily Integration: If
- Native Google Search Grounding:
In gemini_api.py:
- Register a new config variable
GEMINI_SEARCH_GROUNDING(Boolean, defaultFalse). - In
_http_generate_content_from_rendered(), if enabled, inject{"googleSearch": {}}directly into thetoolslist in the HTTP payload. This enables native Google Search grounding for Gemini models. - In
_http_generate_content(), if enabled, injectpayload["tools"] = [{"googleSearch": {}}].
- Register a new config variable
Objective: Utilize G.R.I.L.L.O. background reflection capabilities to evaluate the passage of time when the user is idle.
- G.R.I.L.L.O. Beats: The scheduler is implemented in grillo_impl.py. It automatically loads optional beat plugins from
PLUGIN_REGISTRYthat setBEAT_TYPE. - Introspection Limit: Internal introspective beats (such as
self_reflection) are allowed to return thecreate_personal_diary_entryaction to write thoughts to the diary. This updates the mood state and acts as a trigger for subsequentoutreachbeats (which actually message the user).
- Register Beat Type:
Add
"temporal_reflection": 0.1to the weights dictionaryBEAT_TYPESin grillo_impl.py. In_get_allowed_action_types_for_beat(), return["create_personal_diary_entry"]for"temporal_reflection". - New Beat Plugin:
Create a new plugin
plugins/grillo/grillo_temporal_reflection.py:- Set
BEAT_TYPE = "temporal_reflection". - Calculate
TIME_DELTAby querying the DB for the timestamp of the last message sent by the user:Fallback toSELECT timestamp FROM chat_history_cache WHERE sender_id != 'self' ORDER BY timestamp DESC LIMIT 1
ai_diarylatest entry with a non-nulluser_message. - Format the delta into a natural string (e.g.,
"12 hours ago","3 days ago"). - Build and return the prompt:
[SYSTEM: AUTONOMOUS TEMPORAL REFLECTION] Your last interaction with the user was {{TIME_DELTA}} (e.g., 18 hours ago). Reflect on the time elapsed since you last spoke. Does this delay prompt a new realization, a shift in your emotional state (e.g., feeling lonely, curious, or distant), or an inclination to initiate a message? End with a JSON action to write a diary entry with your temporal reflection: {"actions": [{"type": "create_personal_diary_entry", "payload": {"interaction_summary": "brief summary", "personal_thought": "private reflection on the elapsed time", "emotions": [{"type": "longing", "intensity": 0.5}], "content": "your reflection"}}]}
- Set
- Run
uv run pytest tests/test_prompt_engine.pyto identify any failing assertions on prompt context formats, and update tests to assert the[SYSTEM: REALITY ANCHOR]block. - Add unit tests for
get_current_season()intests/test_time_zone_utils.py. - Add integration tests for
plugins/web_search_plugin.pyto verify DuckDuckGo scraper parsing. - Add unit tests for the
temporal_reflectionbeat prompt generation.
- Ask the Synth: "What year is it right now?" -> Acknowledge 2026.
- Ask a question about a recent event post-dating the knowledge cutoff -> Verify that she triggers
search_current_knowledge(or native Google Search) and replies factually. - Verify in
synth.logthat thetemporal_reflectionbeat is loaded, enqueued, and parsed.