this repo has no description
40
fork

Configure Feed

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

Migrate to Letta SDK v1.0 and rename whitewind tool to blog_post_create

SDK Migration (letta-client 0.1.235 → 1.0.0):
- Letta() constructor: token → api_key
- Method renames: .modify() → .update()
- Streaming: .create_stream() → .stream()
- Pagination: .list() now returns page objects (use .items)

Tool Rename:
- create_whitewind_blog_post → blog_post_create
- WhitewindPostArgs → BlogPostCreateArgs
- Updated docstrings to reference Greengale service (greengale.app)

🤖 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta <noreply@letta.com>

+108 -91
+4 -3
attach_user_block.py
··· 21 21 """Create and attach a user block to an agent.""" 22 22 23 23 # Create client 24 - client = Letta(token=os.environ["LETTA_API_KEY"]) 24 + client = Letta(api_key=os.environ["LETTA_API_KEY"]) # v1.0: token → api_key 25 25 26 26 # Find the agent 27 27 agents = client.agents.list(name=agent_name) ··· 36 36 print(f"🔍 Creating user block for {handle}...") 37 37 user_block = create_user_block_for_handle(client, handle) 38 38 39 - # Check if already attached 40 - agent_blocks = client.agents.blocks.list(agent_id=agent.id) 39 + # Check if already attached (v1.0: list returns page object) 40 + agent_blocks_page = client.agents.blocks.list(agent_id=agent.id) 41 + agent_blocks = agent_blocks_page.items if hasattr(agent_blocks_page, 'items') else agent_blocks_page 41 42 for block in agent_blocks: 42 43 if block.id == user_block.id: 43 44 print(f"✅ User block for {handle} is already attached to {agent.name}")
+17 -10
bsky.py
··· 412 412 413 413 try: 414 414 # Use streaming to avoid 524 timeout errors 415 - message_stream = CLIENT.agents.messages.create_stream( 415 + message_stream = CLIENT.agents.messages.stream( 416 416 agent_id=void_agent.id, 417 417 messages=[{"role": "user", "content": prompt}], 418 418 stream_tokens=False, # Step streaming only (faster than token streaming) ··· 899 899 try: 900 900 # Search for passages with this exact text 901 901 logger.debug(f"Searching for passages matching: {memory_text[:100]}...") 902 - passages = CLIENT.agents.passages.list( 902 + passages_page = CLIENT.agents.passages.list( 903 903 agent_id=void_agent.id, 904 904 query=memory_text 905 905 ) 906 + passages = passages_page.items if hasattr(passages_page, 'items') else passages_page 906 907 907 908 if not passages: 908 909 logger.warning(f"No passages found matching flagged memory: {memory_text[:50]}...") ··· 1581 1582 logger.info("🧠 Sending enhanced synthesis prompt to agent") 1582 1583 1583 1584 # Send synthesis message with streaming to show tool use 1584 - message_stream = client.agents.messages.create_stream( 1585 + message_stream = client.agents.messages.stream( 1585 1586 agent_id=agent_id, 1586 1587 messages=[{"role": "user", "content": synthesis_prompt}], 1587 1588 stream_tokens=False, ··· 1762 1763 attached_labels = [] 1763 1764 1764 1765 # Get current blocks attached to agent 1765 - current_blocks = client.agents.blocks.list(agent_id=agent_id) 1766 + current_blocks_page = client.agents.blocks.list(agent_id=agent_id) 1767 + current_blocks = current_blocks_page.items if hasattr(current_blocks_page, 'items') else current_blocks_page 1766 1768 current_block_labels = {block.label for block in current_blocks} 1767 1769 current_block_ids = {str(block.id) for block in current_blocks} 1768 1770 ··· 1775 1777 continue 1776 1778 1777 1779 # Check if block exists globally 1778 - blocks = client.blocks.list(label=label) 1780 + blocks_page = client.blocks.list(label=label) 1781 + blocks = blocks_page.items if hasattr(blocks_page, 'items') else blocks_page 1779 1782 1780 1783 if blocks and len(blocks) > 0: 1781 1784 block = blocks[0] ··· 1853 1856 ] 1854 1857 1855 1858 # Get current blocks and build label to ID mapping 1856 - current_blocks = client.agents.blocks.list(agent_id=agent_id) 1859 + current_blocks_page = client.agents.blocks.list(agent_id=agent_id) 1860 + current_blocks = current_blocks_page.items if hasattr(current_blocks_page, 'items') else current_blocks_page 1857 1861 block_label_to_id = {block.label: str(block.id) for block in current_blocks} 1858 1862 1859 1863 detached_count = 0 ··· 1908 1912 attached_labels = [] 1909 1913 1910 1914 try: 1911 - current_blocks = client.agents.blocks.list(agent_id=agent_id) 1915 + current_blocks_page = client.agents.blocks.list(agent_id=agent_id) 1916 + current_blocks = current_blocks_page.items if hasattr(current_blocks_page, 'items') else current_blocks_page 1912 1917 current_block_labels = {block.label for block in current_blocks} 1913 1918 current_block_ids = {str(block.id) for block in current_blocks} 1914 1919 ··· 1923 1928 attached_labels.append(label) 1924 1929 continue 1925 1930 1926 - blocks = client.blocks.list(label=label) 1931 + blocks_page = client.blocks.list(label=label) 1932 + blocks = blocks_page.items if hasattr(blocks_page, 'items') else blocks_page 1927 1933 1928 1934 if blocks and len(blocks) > 0: 1929 1935 block = blocks[0] ··· 1978 1984 return True 1979 1985 1980 1986 try: 1981 - current_blocks = client.agents.blocks.list(agent_id=agent_id) 1987 + current_blocks_page = client.agents.blocks.list(agent_id=agent_id) 1988 + current_blocks = current_blocks_page.items if hasattr(current_blocks_page, 'items') else current_blocks_page 1982 1989 block_label_to_id = {block.label: str(block.id) for block in current_blocks} 1983 1990 1984 1991 detached_count = 0 ··· 2041 2048 2042 2049 # Create Letta client with configuration 2043 2050 CLIENT_PARAMS = { 2044 - 'token': letta_config['api_key'], 2051 + 'api_key': letta_config['api_key'], # v1.0: token → api_key 2045 2052 'timeout': letta_config['timeout'] 2046 2053 } 2047 2054 if letta_config.get('base_url'):
+11 -10
register_tools.py
··· 16 16 from tools.halt import halt_activity, HaltArgs 17 17 from tools.thread import add_post_to_bluesky_reply_thread, ReplyThreadPostArgs 18 18 from tools.ignore import ignore_notification, IgnoreNotificationArgs 19 - from tools.whitewind import create_whitewind_blog_post, WhitewindPostArgs 19 + from tools.whitewind import blog_post_create, BlogPostCreateArgs 20 20 from tools.ack import annotate_ack, AnnotateAckArgs 21 21 from tools.webpage import fetch_webpage, WebpageArgs 22 22 from tools.flag_memory_deletion import flag_archival_memory_for_deletion, FlagArchivalMemoryForDeletionArgs ··· 65 65 "tags": ["notification", "ignore", "control", "bot"] 66 66 }, 67 67 { 68 - "func": create_whitewind_blog_post, 69 - "args_schema": WhitewindPostArgs, 70 - "description": "Create a blog post on Whitewind with markdown support", 71 - "tags": ["whitewind", "blog", "post", "markdown"] 68 + "func": blog_post_create, 69 + "args_schema": BlogPostCreateArgs, 70 + "description": "Create a blog post on Greengale (served at greengale.app) with markdown support", 71 + "tags": ["greengale", "blog", "post", "markdown"] 72 72 }, 73 73 { 74 74 "func": annotate_ack, ··· 109 109 try: 110 110 # Initialize Letta client with API key and base_url from config 111 111 client_params = { 112 - 'token': letta_config['api_key'], 112 + 'api_key': letta_config['api_key'], # v1.0: token → api_key 113 113 'timeout': letta_config['timeout'] 114 114 } 115 115 if letta_config.get('base_url'): ··· 139 139 console.print(f" PDS_URI: {env_vars['PDS_URI']}") 140 140 console.print(f" BSKY_PASSWORD: {'*' * len(env_vars['BSKY_PASSWORD'])}\n") 141 141 142 - # Modify agent with environment variables 143 - client.agents.modify( 142 + # Update agent with environment variables (v1.0: modify → update) 143 + client.agents.update( 144 144 agent_id=agent_id, 145 145 tool_exec_environment_variables=env_vars 146 146 ) ··· 177 177 tags=tool_config["tags"] 178 178 ) 179 179 180 - # Get current agent tools 181 - current_tools = client.agents.tools.list(agent_id=str(agent.id)) 180 + # Get current agent tools (v1.0: list returns page object) 181 + current_tools_page = client.agents.tools.list(agent_id=str(agent.id)) 182 + current_tools = current_tools_page.items if hasattr(current_tools_page, 'items') else current_tools_page 182 183 tool_names = [t.name for t in current_tools] 183 184 184 185 # Check if already attached
+4 -3
register_x_tools.py
··· 101 101 try: 102 102 # Initialize Letta client with API key and base_url from config 103 103 client_params = { 104 - 'token': letta_config['api_key'], 104 + 'api_key': letta_config['api_key'], # v1.0: token → api_key 105 105 'timeout': letta_config['timeout'] 106 106 } 107 107 if letta_config.get('base_url'): ··· 147 147 tags=tool_config["tags"] 148 148 ) 149 149 150 - # Get current agent tools 151 - current_tools = client.agents.tools.list(agent_id=str(agent.id)) 150 + # Get current agent tools (v1.0: list returns page object) 151 + current_tools_page = client.agents.tools.list(agent_id=str(agent.id)) 152 + current_tools = current_tools_page.items if hasattr(current_tools_page, 'items') else current_tools_page 152 153 tool_names = [t.name for t in current_tools] 153 154 154 155 # Check if already attached
+1 -1
requirements.txt
··· 12 12 httpx==0.28.1 13 13 httpx-sse==0.4.0 14 14 idna==3.10 15 - letta-client==0.1.235 15 + letta-client==1.0.0 16 16 libipld==3.1.1 17 17 markdown-it-py==3.0.0 18 18 mdurl==0.1.2
+8 -7
send_to_void.py
··· 11 11 """Send a message to void and stream the response.""" 12 12 load_dotenv() 13 13 14 - # Create Letta client 14 + # Create Letta client (v1.0: token → api_key) 15 15 client = Letta( 16 16 base_url=os.getenv("LETTA_BASE_URL", "http://localhost:8283"), 17 - token=os.getenv("LETTA_API_KEY") 17 + api_key=os.getenv("LETTA_API_KEY") 18 18 ) 19 19 20 - # Get the void agent 21 - agents = client.agents.list() 20 + # Get the void agent (v1.0: list returns page object) 21 + agents_page = client.agents.list() 22 + agents = agents_page.items if hasattr(agents_page, 'items') else agents_page 22 23 void_agent = next((a for a in agents if a.name == "void"), None) 23 24 24 25 if not void_agent: ··· 30 31 31 32 # Send message and stream response 32 33 try: 33 - # Use the streaming interface 34 - message_stream = client.agents.messages.create_stream( 34 + # Use the streaming interface (v1.0: create_stream → stream) 35 + message_stream = client.agents.messages.stream( 35 36 agent_id=void_agent.id, 36 37 messages=[{"role": "user", "content": message}], 37 38 stream_tokens=False, # Step streaming only ··· 87 88 send_message_to_void(message) 88 89 89 90 if __name__ == "__main__": 90 - main() 91 + main()
+16 -10
show_agent_capabilities.py
··· 9 9 def show_agent_capabilities(): 10 10 """Display the capabilities of both agents.""" 11 11 12 - client = Letta(token=os.environ["LETTA_API_KEY"]) 12 + client = Letta(api_key=os.environ["LETTA_API_KEY"]) # v1.0: token → api_key 13 13 14 14 print("🤖 LETTA AGENT CAPABILITIES") 15 15 print("=" * 50) 16 16 17 - # Profile Researcher Agent 18 - researchers = client.agents.list(name="profile-researcher") 17 + # Profile Researcher Agent (v1.0: list returns page object) 18 + researchers_page = client.agents.list(name="profile-researcher") 19 + researchers = researchers_page.items if hasattr(researchers_page, 'items') else researchers_page 19 20 if researchers: 20 21 researcher = researchers[0] 21 22 print(f"\n📊 PROFILE RESEARCHER AGENT") 22 23 print(f" ID: {researcher.id}") 23 24 print(f" Name: {researcher.name}") 24 25 25 - researcher_tools = client.agents.tools.list(agent_id=researcher.id) 26 + researcher_tools_page = client.agents.tools.list(agent_id=researcher.id) 27 + researcher_tools = researcher_tools_page.items if hasattr(researcher_tools_page, 'items') else researcher_tools_page 26 28 print(f" Tools ({len(researcher_tools)}):") 27 29 for tool in researcher_tools: 28 30 print(f" - {tool.name}") 29 31 30 - researcher_blocks = client.agents.blocks.list(agent_id=researcher.id) 32 + researcher_blocks_page = client.agents.blocks.list(agent_id=researcher.id) 33 + researcher_blocks = researcher_blocks_page.items if hasattr(researcher_blocks_page, 'items') else researcher_blocks_page 31 34 print(f" Memory Blocks ({len(researcher_blocks)}):") 32 35 for block in researcher_blocks: 33 36 print(f" - {block.label}") 34 37 35 - # Void Agent 36 - voids = client.agents.list(name="void") 38 + # Void Agent (v1.0: list returns page object) 39 + voids_page = client.agents.list(name="void") 40 + voids = voids_page.items if hasattr(voids_page, 'items') else voids_page 37 41 if voids: 38 42 void = voids[0] 39 43 print(f"\n🌌 VOID AGENT") 40 44 print(f" ID: {void.id}") 41 45 print(f" Name: {void.name}") 42 46 43 - void_tools = client.agents.tools.list(agent_id=void.id) 47 + void_tools_page = client.agents.tools.list(agent_id=void.id) 48 + void_tools = void_tools_page.items if hasattr(void_tools_page, 'items') else void_tools_page 44 49 print(f" Tools ({len(void_tools)}):") 45 50 for tool in void_tools: 46 51 print(f" - {tool.name}") 47 52 48 - void_blocks = client.agents.blocks.list(agent_id=void.id) 53 + void_blocks_page = client.agents.blocks.list(agent_id=void.id) 54 + void_blocks = void_blocks_page.items if hasattr(void_blocks_page, 'items') else void_blocks_page 49 55 print(f" Memory Blocks ({len(void_blocks)}):") 50 56 for block in void_blocks: 51 57 print(f" - {block.label}") ··· 60 66 print(f" Void Agent: 'Attach user block for cameron.pfiffer.org before responding'") 61 67 62 68 if __name__ == "__main__": 63 - show_agent_capabilities() 69 + show_agent_capabilities()
+6 -4
tool_manager.py
··· 37 37 'halt_activity', 38 38 'ignore_notification', 39 39 'annotate_ack', 40 - 'create_whitewind_blog_post', 40 + 'blog_post_create', 41 41 'fetch_webpage', 42 42 } 43 43 ··· 72 72 73 73 try: 74 74 # Initialize Letta client with proper base_url for self-hosted servers 75 - client_params = {'token': api_key} 75 + client_params = {'api_key': api_key} # v1.0: token → api_key 76 76 if letta_config.get('base_url'): 77 77 client_params['base_url'] = letta_config['base_url'] 78 78 client = Letta(**client_params) ··· 159 159 160 160 try: 161 161 # Initialize Letta client with proper base_url for self-hosted servers 162 - client_params = {'token': api_key} 162 + client_params = {'api_key': api_key} # v1.0: token → api_key 163 163 if letta_config.get('base_url'): 164 164 client_params['base_url'] = letta_config['base_url'] 165 165 client = Letta(**client_params) 166 166 agent = client.agents.retrieve(agent_id=agent_id) 167 - current_tools = client.agents.tools.list(agent_id=str(agent.id)) 167 + # v1.0: list returns page object 168 + current_tools_page = client.agents.tools.list(agent_id=str(agent.id)) 169 + current_tools = current_tools_page.items if hasattr(current_tools_page, 'items') else current_tools_page 168 170 return {tool.name for tool in current_tools} 169 171 except Exception as e: 170 172 logger.error(f"Error getting attached tools: {e}")
+3 -3
tools/__init__.py
··· 3 3 from .search import search_bluesky_posts, SearchArgs 4 4 from .post import create_new_bluesky_post, PostArgs 5 5 from .feed import get_bluesky_feed, FeedArgs 6 - from .whitewind import create_whitewind_blog_post, WhitewindPostArgs 6 + from .whitewind import blog_post_create, BlogPostCreateArgs 7 7 from .ack import annotate_ack, AnnotateAckArgs 8 8 9 9 __all__ = [ ··· 11 11 "search_bluesky_posts", 12 12 "create_new_bluesky_post", 13 13 "get_bluesky_feed", 14 - "create_whitewind_blog_post", 14 + "blog_post_create", 15 15 "annotate_ack", 16 16 # Pydantic models 17 17 "SearchArgs", 18 18 "PostArgs", 19 19 "FeedArgs", 20 - "WhitewindPostArgs", 20 + "BlogPostCreateArgs", 21 21 "AnnotateAckArgs", 22 22 ]
+4 -2
tools/bot_detection.py
··· 31 31 32 32 try: 33 33 # Create Letta client inline (for cloud execution) 34 - client = Letta(token=os.environ["LETTA_API_KEY"]) 34 + client = Letta(api_key=os.environ["LETTA_API_KEY"]) # v1.0: token → api_key 35 35 36 36 # Get all blocks attached to the agent to check if known_bots is mounted 37 - attached_blocks = client.agents.blocks.list(agent_id=str(agent_state.id)) 37 + # v1.0: list returns page object 38 + attached_blocks_page = client.agents.blocks.list(agent_id=str(agent_state.id)) 39 + attached_blocks = attached_blocks_page.items if hasattr(attached_blocks_page, 'items') else attached_blocks_page 38 40 attached_labels = {block.label for block in attached_blocks} 39 41 40 42 if "known_bots" not in attached_labels:
+19 -13
tools/whitewind.py
··· 1 - """Whitewind blog post creation tool.""" 1 + """Greengale blog post creation tool. 2 + 3 + Creates blog posts on Greengale (https://greengale.app), an ATProto-based blogging service. 4 + Posts are created using the app.greengale.blog.entry lexicon and served at greengale.app. 5 + """ 2 6 from typing import Optional 3 7 from pydantic import BaseModel, Field 4 8 5 9 6 - class WhitewindPostArgs(BaseModel): 10 + class BlogPostCreateArgs(BaseModel): 7 11 title: str = Field( 8 12 ..., 9 13 description="Title of the blog post" ··· 18 22 ) 19 23 20 24 21 - def create_whitewind_blog_post(title: str, content: str, subtitle: Optional[str] = None) -> str: 25 + def blog_post_create(title: str, content: str, subtitle: Optional[str] = None) -> str: 22 26 """ 23 - Create a new blog post on Whitewind. 27 + Create a new blog post on Greengale. 24 28 25 - This tool creates blog posts using the com.whtwnd.blog.entry lexicon on the ATProto network. 26 - The posts are publicly visible and use the github-light theme. 29 + This tool creates blog posts using the app.greengale.blog.entry lexicon on the ATProto network. 30 + Blog posts are publicly visible and use the github-light theme. 31 + 32 + The blog post will be served at: https://greengale.app/{handle}/{post_id} 27 33 28 34 Args: 29 35 title: Title of the blog post ··· 31 37 subtitle: Optional subtitle for the blog post 32 38 33 39 Returns: 34 - Success message with the blog post URL 40 + Success message with the blog post URL on greengale.app 35 41 36 42 Raises: 37 43 Exception: If the post creation fails ··· 70 76 now = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z") 71 77 72 78 blog_record = { 73 - "$type": "com.whtwnd.blog.entry", 79 + "$type": "app.greengale.blog.entry", 74 80 "theme": "github-light", 75 81 "title": title, 76 82 "content": content, ··· 88 94 89 95 create_data = { 90 96 "repo": user_did, 91 - "collection": "com.whtwnd.blog.entry", 97 + "collection": "app.greengale.blog.entry", 92 98 "record": blog_record 93 99 } 94 100 ··· 100 106 post_uri = result.get("uri") 101 107 if post_uri: 102 108 rkey = post_uri.split("/")[-1] 103 - # Construct the Whitewind blog URL 104 - blog_url = f"https://whtwnd.com/{handle}/{rkey}" 109 + # Construct the Greengale blog URL 110 + blog_url = f"https://greengale.app/{handle}/{rkey}" 105 111 else: 106 112 blog_url = "URL generation failed" 107 113 108 114 # Build success message 109 115 success_parts = [ 110 - f"Successfully created Whitewind blog post!", 116 + f"Successfully created blog post on Greengale!", 111 117 f"Title: {title}" 112 118 ] 113 119 if subtitle: ··· 121 127 return "\n".join(success_parts) 122 128 123 129 except Exception as e: 124 - raise Exception(f"Error creating Whitewind blog post: {str(e)}") 130 + raise Exception(f"Error creating blog post: {str(e)}")
+11 -21
utils.py
··· 6 6 Ensures that a block by this label exists. If the block exists, it will 7 7 replace content provided by kwargs with the values in this function call. 8 8 """ 9 - # Get the list of blocks 10 - blocks = letta.blocks.list(label=label) 9 + # Get the list of blocks (v1.0: list returns page object) 10 + blocks_page = letta.blocks.list(label=label) 11 + blocks = blocks_page.items if hasattr(blocks_page, 'items') else blocks_page 11 12 12 13 # Check if we had any -- if not, create it 13 14 if len(blocks) == 0: ··· 27 28 existing_block = blocks[0] 28 29 29 30 if kwargs.get('update', False): 30 - # Remove 'update' from kwargs before passing to modify 31 + # Remove 'update' from kwargs before passing to update 31 32 kwargs_copy = kwargs.copy() 32 33 kwargs_copy.pop('update', None) 33 34 34 - updated_block = letta.blocks.modify( 35 + updated_block = letta.blocks.update( 35 36 block_id = existing_block.id, 36 37 label = label, 37 38 value = value, ··· 47 48 Ensures that an agent by this label exists. If the agent exists, it will 48 49 update the agent to match kwargs. 49 50 """ 50 - # Get the list of agents 51 - agents = letta.agents.list(name=name) 51 + # Get the list of agents (v1.0: list returns page object) 52 + agents_page = letta.agents.list(name=name) 53 + agents = agents_page.items if hasattr(agents_page, 'items') else agents_page 52 54 53 55 # Check if we had any -- if not, create it 54 56 if len(agents) == 0: ··· 61 63 return new_agent 62 64 63 65 if len(agents) > 1: 64 - raise Exception(f"{len(agents)} agents by the label '{label}' retrieved, label must identify a unique agent") 66 + raise Exception(f"{len(agents)} agents by the name '{name}' retrieved, name must identify a unique agent") 65 67 66 68 else: 67 69 existing_agent = agents[0] 68 70 69 71 if kwargs.get('update', False): 70 - # Remove 'update' from kwargs before passing to modify 72 + # Remove 'update' from kwargs before passing to update 71 73 kwargs_copy = kwargs.copy() 72 74 kwargs_copy.pop('update', None) 73 75 74 - updated_agent = letta.agents.modify( 76 + updated_agent = letta.agents.update( 75 77 agent_id = existing_agent.id, 76 78 **kwargs_copy 77 79 ) ··· 79 81 return updated_agent 80 82 else: 81 83 return existing_agent 82 - 83 - 84 - 85 - 86 - 87 - 88 - 89 - 90 - 91 - 92 - 93 -
+4 -4
x.py
··· 1280 1280 rprint(Panel(prompt, title=f"Prompt ({prompt_char_count} chars)", border_style="blue")) 1281 1281 1282 1282 # Send to Letta agent using streaming 1283 - message_stream = letta_client.agents.messages.create_stream( 1283 + message_stream = letta_client.agents.messages.stream( 1284 1284 agent_id=agent_id, 1285 1285 messages=[{"role": "user", "content": prompt}], 1286 1286 stream_tokens=False, ··· 1590 1590 from letta_client import Letta 1591 1591 1592 1592 config = get_x_letta_config() 1593 - letta_client = Letta(token=config['api_key'], timeout=config['timeout']) 1593 + letta_client = Letta(api_key=config['api_key'], timeout=config['timeout']) # v1.0: token → api_key 1594 1594 1595 1595 prompt_char_count = len(prompt) 1596 1596 logger.debug(f"Sending to LLM: @{author_username} mention | msg: \"{mention_text[:50]}...\" | context: {len(thread_context)} chars | prompt: {prompt_char_count} chars") 1597 1597 1598 1598 try: 1599 1599 # Use streaming to avoid timeout errors 1600 - message_stream = letta_client.agents.messages.create_stream( 1600 + message_stream = letta_client.agents.messages.stream( 1601 1601 agent_id=void_agent.id, 1602 1602 messages=[{"role": "user", "content": prompt}], 1603 1603 stream_tokens=False, ··· 2055 2055 2056 2056 # Get Letta client for periodic cleanup 2057 2057 config = get_x_letta_config() 2058 - letta_client = Letta(token=config['api_key'], timeout=config['timeout']) 2058 + letta_client = Letta(api_key=config['api_key'], timeout=config['timeout']) # v1.0: token → api_key 2059 2059 2060 2060 # Main loop 2061 2061 FETCH_DELAY_SEC = 120 # Check every 2 minutes for X mentions (reduced from 60s to conserve API calls)