a digital entity named phi that roams bsky phi.zzstoatzz.io
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

surface timestamps in recall results, add UTC clock to system prompt

recall results now show (YYYY-MM-DD) so phi can distinguish "this was
current on april 6" from "this is current now." system prompt changed
from [TODAY] date-only to [NOW] with time and explicit UTC timezone.

fixes confabulation where phi posted 5-day-old news as current because
memory notes contained relative time words ("right now", "today") with
no visible date anchor.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

+18 -6
+3 -2
src/bot/agent.py
··· 4 4 import logging 5 5 import os 6 6 from collections.abc import Sequence 7 - from datetime import date 7 + from datetime import UTC, datetime 8 8 from pathlib import Path 9 9 10 10 from pydantic_ai import Agent, ImageUrl, RunContext ··· 162 162 163 163 @self.agent.system_prompt(dynamic=True) 164 164 def inject_today() -> str: 165 - return f"[TODAY]: {date.today().isoformat()}" 165 + now = datetime.now(UTC) 166 + return f"[NOW]: {now.strftime('%Y-%m-%d %H:%M UTC')}" 166 167 167 168 @self.agent.system_prompt(dynamic=True) 168 169 def inject_notifications(ctx: RunContext[PhiDeps]) -> str:
+15 -4
src/bot/tools/_helpers.py
··· 92 92 return "\n\n".join(lines) 93 93 94 94 95 + def _short_date(iso: str) -> str: 96 + """Extract YYYY-MM-DD from an ISO timestamp, or return '' if missing.""" 97 + return iso[:10] if iso and len(iso) >= 10 else "" 98 + 99 + 95 100 def _format_user_results(results: list[dict], handle: str) -> list[str]: 96 101 parts = [] 97 102 for r in results: ··· 99 104 content = r.get("content", "") 100 105 tags = r.get("tags", []) 101 106 tag_str = f"[{', '.join(tags)}]" if tags else "" 102 - parts.append(f"[{kind}]{tag_str} {content}") 107 + date = _short_date(r.get("created_at", "")) 108 + date_str = f" ({date})" if date else "" 109 + parts.append(f"[{kind}]{tag_str}{date_str} {content}") 103 110 return parts 104 111 105 112 ··· 107 114 parts = [] 108 115 for r in results: 109 116 tags = f" [{', '.join(r['tags'])}]" if r.get("tags") else "" 110 - parts.append(f"{r['content']}{tags}") 117 + date = _short_date(r.get("created_at", "")) 118 + date_str = f" ({date})" if date else "" 119 + parts.append(f"[note]{tags}{date_str} {r['content']}") 111 120 return parts 112 121 113 122 ··· 118 127 content = r.get("content", "") 119 128 tags = r.get("tags", []) 120 129 tag_str = f" [{', '.join(tags)}]" if tags else "" 130 + date = _short_date(r.get("created_at", "")) 131 + date_str = f" ({date})" if date else "" 121 132 if source == "user": 122 133 kind = r.get("kind", "unknown") 123 - parts.append(f"[@{handle} {kind}]{tag_str} {content}") 134 + parts.append(f"[@{handle} {kind}]{tag_str}{date_str} {content}") 124 135 else: 125 - parts.append(f"[note]{tag_str} {content}") 136 + parts.append(f"[note]{tag_str}{date_str} {content}") 126 137 return parts 127 138 128 139