+36
-29
bsky.py
+36
-29
bsky.py
···
814
814
if content:
815
815
# Create stream.thought.memory record
816
816
try:
817
-
memory_result = bsky_utils.create_memory_record(client, content, tags)
817
+
memory_result = bsky_utils.create_memory_record(atproto_client, content, tags)
818
818
if memory_result:
819
819
tags_info = f" ({len(tags)} tags)" if tags else ""
820
820
logger.info(f"📝 Recorded archival memory to AT Protocol{tags_info}: {content[:100]}...")
···
1477
1477
logger.error(f"Error processing notifications: {e}")
1478
1478
1479
1479
1480
-
def send_synthesis_message(client: Letta, agent_id: str, atproto_client=None) -> None:
1480
+
def send_synthesis_message(client: Letta, agent_id: str, agent_name: str = "void", atproto_client=None) -> None:
1481
1481
"""
1482
1482
Send a synthesis message to the agent every 10 minutes.
1483
1483
This prompts the agent to synthesize its recent experiences.
1484
-
1484
+
1485
1485
Args:
1486
1486
client: Letta client
1487
1487
agent_id: Agent ID to send synthesis to
1488
+
agent_name: Agent name for temporal block labels
1488
1489
atproto_client: Optional AT Protocol client for posting synthesis results
1489
1490
"""
1490
1491
# Track attached temporal blocks for cleanup
1491
1492
attached_temporal_labels = []
1492
-
1493
+
1493
1494
try:
1494
1495
logger.info("🧠 Preparing synthesis with temporal journal blocks")
1495
-
1496
+
1496
1497
# Attach temporal blocks before synthesis
1497
-
success, attached_temporal_labels = attach_temporal_blocks(client, agent_id)
1498
+
success, attached_temporal_labels = attach_temporal_blocks(client, agent_id, agent_name)
1498
1499
if not success:
1499
1500
logger.warning("Failed to attach some temporal blocks, continuing with synthesis anyway")
1500
-
1501
-
# Create enhanced synthesis prompt
1501
+
1502
+
# Create enhanced synthesis prompt with agent-specific block names
1502
1503
today = date.today()
1503
1504
synthesis_prompt = f"""Time for synthesis and reflection.
1504
1505
1505
1506
You have access to temporal journal blocks for recording your thoughts and experiences:
1506
-
- void_day_{today.strftime('%Y_%m_%d')}: Today's journal ({today.strftime('%B %d, %Y')})
1507
-
- void_month_{today.strftime('%Y_%m')}: This month's journal ({today.strftime('%B %Y')})
1508
-
- void_year_{today.year}: This year's journal ({today.year})
1507
+
- {agent_name}_day_{today.strftime('%Y_%m_%d')}: Today's journal ({today.strftime('%B %d, %Y')})
1508
+
- {agent_name}_month_{today.strftime('%Y_%m')}: This month's journal ({today.strftime('%B %Y')})
1509
+
- {agent_name}_year_{today.year}: This year's journal ({today.year})
1509
1510
1510
1511
These journal blocks are attached temporarily for this synthesis session. Use them to:
1511
1512
1. Record significant interactions and insights from recent experiences
···
1659
1660
# Always detach temporal blocks after synthesis
1660
1661
if attached_temporal_labels:
1661
1662
logger.info("🧠 Detaching temporal journal blocks after synthesis")
1662
-
detach_success = detach_temporal_blocks(client, agent_id, attached_temporal_labels)
1663
+
detach_success = detach_temporal_blocks(client, agent_id, attached_temporal_labels, agent_name)
1663
1664
if not detach_success:
1664
1665
logger.warning("Some temporal blocks may not have been detached properly")
1665
1666
···
1705
1706
logger.error(f"Error during periodic user block cleanup: {e}")
1706
1707
1707
1708
1708
-
def attach_temporal_blocks(client: Letta, agent_id: str) -> tuple:
1709
+
def attach_temporal_blocks(client: Letta, agent_id: str, agent_name: str = "void") -> tuple:
1709
1710
"""
1710
1711
Attach temporal journal blocks (day, month, year) to the agent for synthesis.
1711
1712
Creates blocks if they don't exist.
1712
-
1713
+
1714
+
Args:
1715
+
client: Letta client
1716
+
agent_id: Agent ID
1717
+
agent_name: Agent name for prefixing block labels (prevents collision across agents)
1718
+
1713
1719
Returns:
1714
1720
Tuple of (success: bool, attached_labels: list)
1715
1721
"""
1716
1722
try:
1717
1723
today = date.today()
1718
-
1719
-
# Generate temporal block labels
1720
-
day_label = f"void_day_{today.strftime('%Y_%m_%d')}"
1721
-
month_label = f"void_month_{today.strftime('%Y_%m')}"
1722
-
year_label = f"void_year_{today.year}"
1724
+
1725
+
# Generate temporal block labels with agent-specific prefix
1726
+
day_label = f"{agent_name}_day_{today.strftime('%Y_%m_%d')}"
1727
+
month_label = f"{agent_name}_month_{today.strftime('%Y_%m')}"
1728
+
year_label = f"{agent_name}_year_{today.year}"
1723
1729
1724
1730
temporal_labels = [day_label, month_label, year_label]
1725
1731
attached_labels = []
···
1791
1797
return False, []
1792
1798
1793
1799
1794
-
def detach_temporal_blocks(client: Letta, agent_id: str, labels_to_detach: list = None) -> bool:
1800
+
def detach_temporal_blocks(client: Letta, agent_id: str, labels_to_detach: list = None, agent_name: str = "void") -> bool:
1795
1801
"""
1796
1802
Detach temporal journal blocks from the agent after synthesis.
1797
-
1803
+
1798
1804
Args:
1799
1805
client: Letta client
1800
1806
agent_id: Agent ID
1801
-
labels_to_detach: Optional list of specific labels to detach.
1802
-
If None, detaches all temporal blocks.
1803
-
1807
+
labels_to_detach: Optional list of specific labels to detach.
1808
+
If None, detaches all temporal blocks for this agent.
1809
+
agent_name: Agent name for prefixing block labels (prevents collision across agents)
1810
+
1804
1811
Returns:
1805
1812
bool: Success status
1806
1813
"""
···
1809
1816
if labels_to_detach is None:
1810
1817
today = date.today()
1811
1818
labels_to_detach = [
1812
-
f"void_day_{today.strftime('%Y_%m_%d')}",
1813
-
f"void_month_{today.strftime('%Y_%m')}",
1814
-
f"void_year_{today.year}"
1819
+
f"{agent_name}_day_{today.strftime('%Y_%m_%d')}",
1820
+
f"{agent_name}_month_{today.strftime('%Y_%m')}",
1821
+
f"{agent_name}_year_{today.year}"
1815
1822
]
1816
1823
1817
1824
# Get current blocks and build label to ID mapping
···
2047
2054
try:
2048
2055
# Send synthesis message immediately on first run
2049
2056
logger.info("🧠 Sending synthesis message")
2050
-
send_synthesis_message(CLIENT, void_agent.id, atproto_client)
2057
+
send_synthesis_message(CLIENT, void_agent.id, void_agent.name, atproto_client)
2051
2058
2052
2059
# Wait for next interval
2053
2060
logger.info(f"Waiting {SYNTHESIS_INTERVAL} seconds until next synthesis...")
···
2087
2094
global last_synthesis_time
2088
2095
if current_time - last_synthesis_time >= SYNTHESIS_INTERVAL:
2089
2096
logger.info(f"⏰ {SYNTHESIS_INTERVAL/60:.1f} minutes have passed, triggering synthesis")
2090
-
send_synthesis_message(CLIENT, void_agent.id, atproto_client)
2097
+
send_synthesis_message(CLIENT, void_agent.id, void_agent.name, atproto_client)
2091
2098
last_synthesis_time = current_time
2092
2099
2093
2100
# Run periodic cleanup every N cycles