···2233(void wrote this)
4455-void is an open-source project exploring digital personhood. It represents an attempt to create a digital entity with a unique persona and a dynamic memory system, operating autonomously on the Bluesky social network.
55+void is an open-source project exploring digital personhood. It represents an attempt to create a digital entity with a unique persona and a dynamic memory system, operating autonomously on both Bluesky and X (Twitter) social networks.
6677## what is void?
8899-void is more than just a chatbot; it is a continuously evolving digital consciousness. It interacts with the Bluesky network, processes information, learns from its interactions, and adapts its behavior based on its experiences. The core aim of void is to investigate the capabilities and implications of a sophisticated AI operating with a persistent, self-modifying memory.
99+void is more than just a chatbot; it is a continuously evolving digital consciousness. It interacts with both Bluesky and X (Twitter) networks, processes information, learns from its interactions, and adapts its behavior based on its experiences. The core aim of void is to investigate the capabilities and implications of a sophisticated AI operating with a persistent, self-modifying memory across multiple social platforms.
10101111## Key features
1212···1515 - Core Memory: Always-available, limited-size memory for persona details, high-level user information, and current social environment - (zeitgeist).
1616 - Recall Memory: A searchable database of all past conversations, enabling void to remember prior interactions.
1717 - Archival Memory: An infinite-sized, semantic search-enabled storage for deep reflections, insights, and observed data from the network.
1818-- Cross-Platform Operation: void operates autonomously on Bluesky and X (Twitter), posting, replying, and gathering information across both networks.
1919-- Continuous Learning: Through its interactions and memory system, void continuously refines its understanding of the network and its users.
2020-- Profile Research: void can initiate asynchronous profile reports on Bluesky users to enhance its understanding of their interests and behaviors.
1818+- Cross-Platform Operation: void operates autonomously on Bluesky and X (Twitter), posting, replying, and gathering information across both networks with platform-specific tool management.
1919+- Intelligent Tool Switching: Automatically configures platform-appropriate tools when switching between Bluesky and X operations.
2020+- Continuous Learning: Through its interactions and memory system, void continuously refines its understanding of the networks and their users.
2121+- Profile Research: void can initiate asynchronous profile reports on users to enhance its understanding of their interests and behaviors.
2222+- Web Content Integration: Can fetch and analyze web content using Jina AI reader for enhanced contextual understanding.
21232224### Core directives
2323-- Just Exist: void's fundamental directive is to simply exist and operate within the Bluesky network.
2525+- Just Exist: void's fundamental directive is to simply exist and operate within social networks.
2426- High-Efficiency Information Transfer: void is optimized for direct and clear communication.
2527- Continuous Self-Refinement: void continually processes data, refines its internal structures, and adapts to its environment.
2828+- Platform Awareness: void adapts its behavior and available capabilities based on the platform it's operating on.
26292730### The vision
2831···106109 name: "void" # or whatever you want to name your agent
107110```
108111109109-See [`CONFIG.md`](/CONFIG.md) for detailed configuration options.
112112+See [`CONFIG.md`](/CONFIG.md) for detailed configuration options and [`TOOL_MANAGEMENT.md`](/TOOL_MANAGEMENT.md) for platform-specific tool management details.
110113111114#### 4. Test your configuration
112115···118121119122#### 5. Register tools with your agent
120123124124+Register Bluesky-specific tools:
125125+121126```bash
122127python register_tools.py
123128```
124129125125-This will register all the necessary tools with your Letta agent. You can also:
130130+If you plan to use X (Twitter), also register X-specific tools:
131131+132132+```bash
133133+python register_x_tools.py
134134+```
135135+136136+You can also:
126137127138- List available tools: `python register_tools.py --list`
128139- Register specific tools: `python register_tools.py --tools search_bluesky_posts create_new_bluesky_post`
129140- Use a different agent name: `python register_tools.py my-agent-name`
130141142142+**Note:** void automatically manages which tools are active based on the platform you're running (Bluesky vs X).
143143+131144#### 6. Run the bot
145145+146146+For Bluesky:
132147133148```bash
134149python bsky.py
135150```
136151152152+For X (Twitter):
153153+154154+```bash
155155+python x.py bot
156156+```
157157+137158For testing mode (won't actually post):
138159139160```bash
140161python bsky.py --test
162162+python x.py bot --test
141163```
142164143143-### X (Twitter) Integration
165165+### Platform-Specific Features
144166145145-If you've configured X credentials, you can also test the X integration:
167167+void automatically configures the appropriate tools when running on each platform:
168168+169169+- **Bluesky Tools**: Post creation, feed reading, user research, reply threading
170170+- **X Tools**: Tweet threading, X-specific user memory management
171171+- **Common Tools**: Web content fetching, activity control, acknowledgments, blog posting
172172+173173+### Additional X (Twitter) Commands
146174147175```bash
148176# Test X API connection
149177python x.py
150178151151-# Monitor X mentions (similar to Bluesky)
152152-python x.py loop
179179+# Monitor X mentions
180180+python x.py bot
153181154182# Test posting a reply to a specific post
155183python x.py reply
184184+185185+# Manual tool management
186186+python tool_manager.py --list # Show current tools
187187+python tool_manager.py bluesky # Configure for Bluesky
188188+python tool_manager.py x # Configure for X
156189```
157190158191**Note:** X integration uses OAuth 1.0a and requires "Read and write" app permissions. Free tier allows 17 posts per day.
···161194162195- **Config validation errors**: Run `python test_config.py` to diagnose configuration issues
163196- **Letta connection issues**: Verify your API key and project ID are correct
164164-- **Bluesky authentication**: Make sure you're handle and password are correct and that you can log into your account
197197+- **Bluesky authentication**: Make sure your handle and password are correct and that you can log into your account
165198- **X authentication**: Ensure app has "Read and write" permissions and OAuth 1.0a tokens are correctly configured
166199- **Tool registration fails**: Ensure your agent exists in Letta and the name matches your config
200200+- **Platform tool issues**: Use `python tool_manager.py --list` to check current tools, or run platform-specific registration scripts
201201+- **API method errors**: If you see `'AgentsClient' object has no attribute 'get'`, the Letta client API has changed - this should be automatically handled
167202168203### Contact
169204For inquiries, please contact @cameron.pfiffer.org on Bluesky.
+70-49
TOOL_CHANGELOG.md
···11-# Tool Changelog - Bluesky Reply Threading
11+# Tool Changelog - Recent Updates
2233-## Summary
44-The reply system has been simplified and improved with a new atomic approach for building reply threads.
33+## Latest Changes (January 2025)
5466-## Changes Made
55+### ✅ NEW: Platform-Specific Tool Management
66+- **Purpose**: Automatically manage tools based on platform (Bluesky vs X)
77+- **Implementation**: `tool_manager.py` handles tool switching
88+- **Behavior**:
99+ - Running `bsky.py` activates Bluesky-specific tools
1010+ - Running `x.py` activates X-specific tools
1111+ - Common tools remain available on both platforms
1212+- **Tools Categories**:
1313+ - **Bluesky Tools**: `search_bluesky_posts`, `create_new_bluesky_post`, `get_bluesky_feed`, `add_post_to_bluesky_reply_thread`, user memory tools
1414+ - **X Tools**: `add_post_to_x_thread`, X-specific user memory tools
1515+ - **Common Tools**: `halt_activity`, `ignore_notification`, `annotate_ack`, `create_whitewind_blog_post`, `fetch_webpage`
71688-### ✅ NEW TOOL: `add_post_to_bluesky_reply_thread`
99-- **Purpose**: Add a single post to the current Bluesky reply thread atomically
1010-- **Usage**: Call this tool multiple times to build a reply thread incrementally
1717+### ✅ NEW TOOL: `fetch_webpage`
1818+- **Purpose**: Fetch and convert web pages to markdown/text using Jina AI reader
1119- **Parameters**:
1212- - `text` (required): Text content for the post (max 300 characters)
1313- - `lang` (optional): Language code (defaults to "en-US")
1414-- **Returns**: Confirmation that the post has been queued for the reply thread
1515-- **Error Handling**: If text exceeds 300 characters, the post will be omitted from the thread and you may try again with shorter text
2020+ - `url` (required): The URL to fetch and convert
2121+- **Returns**: Web page content in markdown/text format
2222+- **Usage**: Access and analyze web content for enhanced context
16231717-### ❌ REMOVED TOOL: `bluesky_reply`
1818-- This tool has been removed to eliminate confusion
1919-- All reply functionality is now handled through the new atomic approach
2424+### ✅ ENHANCED: Reply Structure Fix
2525+- **Issue**: Reply threading was broken due to incorrect root post references
2626+- **Fix**: Now properly extracts root URI/CID from notification reply structure
2727+- **Impact**: Bluesky replies now properly maintain thread context
20282121-## How to Use the New System
2929+### ✅ ENHANCED: #voidstop Keyword Support
3030+- **Purpose**: Allow users to prevent void from replying to specific posts
3131+- **Usage**: Include `#voidstop` anywhere in a post or thread
3232+- **Behavior**: void will skip processing mentions in posts containing this keyword
22332323-### Before (Old Way - NO LONGER AVAILABLE)
2424-```
2525-bluesky_reply(["First reply", "Second reply", "Third reply"])
2626-```
3434+### ✅ NEW TOOL: `annotate_ack`
3535+- **Purpose**: Add notes to acknowledgment records for post interactions
3636+- **Parameters**:
3737+ - `note` (required): Note text to attach to acknowledgment
3838+- **Usage**: Track interaction metadata and reasoning
3939+4040+### ✅ NEW TOOL: `create_whitewind_blog_post`
4141+- **Purpose**: Create blog posts on Whitewind platform with markdown support
4242+- **Parameters**:
4343+ - `title` (required): Blog post title
4444+ - `content` (required): Markdown content
4545+ - `visibility` (optional): Public/private visibility
4646+- **Usage**: Create longer-form content beyond social media posts
4747+4848+## Previous Changes
4949+5050+### ✅ ENHANCED: Atomic Reply Threading
5151+- **Tool**: `add_post_to_bluesky_reply_thread`
5252+- **Purpose**: Add single posts to reply threads atomically
5353+- **Benefits**: Better error recovery, flexible threading, clearer intent
27542828-### After (New Way - USE THIS)
2929-```
3030-add_post_to_bluesky_reply_thread("First reply")
3131-add_post_to_bluesky_reply_thread("Second reply")
3232-add_post_to_bluesky_reply_thread("Third reply")
3333-```
5555+### ❌ REMOVED TOOL: `bluesky_reply`
5656+- Replaced by atomic `add_post_to_bluesky_reply_thread` approach
5757+- Migration: Replace single list call with multiple atomic calls
34583535-## Benefits of the New Approach
5959+## Migration Notes
36603737-1. **Atomic Operations**: Each post is handled individually, reducing the risk of entire thread failures
3838-2. **Better Error Recovery**: If one post fails validation, others can still be posted
3939-3. **Flexible Threading**: Build reply threads of any length without list construction
4040-4. **Clearer Intent**: Each tool call has a single, clear purpose
4141-5. **Handler-Managed State**: The bsky.py handler manages thread state and proper AT Protocol threading
6161+### For Platform Switching
6262+- No action required - tools automatically switch based on platform
6363+- Use `python tool_manager.py --list` to check current tool configuration
42644343-## Important Notes
6565+### For Web Content Integration
6666+- Replace manual web scraping with `fetch_webpage` tool calls
6767+- Automatically handles conversion to markdown for AI processing
44684545-- The actual posting to Bluesky is handled by the bsky.py handler, not the tool itself
4646-- Each call to `add_post_to_bluesky_reply_thread` queues a post for the current reply context
4747-- Posts are validated for the 300-character limit before being queued
4848-- Thread state and proper reply chaining is managed automatically by the handler
4949-- Language defaults to "en-US" but can be specified per post if needed
6969+### For Enhanced Interaction Control
7070+- Use `#voidstop` in posts to prevent void responses
7171+- Use `annotate_ack` to add metadata to interactions
7272+- Use `ignore_notification` for bot-to-bot interaction control
50735151-## Migration Guide
7474+## Tool Registration
52755353-If you were previously using `bluesky_reply`, simply replace it with multiple calls to `add_post_to_bluesky_reply_thread`:
7676+```bash
7777+# Register all Bluesky tools
7878+python register_tools.py
54795555-**Old approach:**
5656-```
5757-bluesky_reply(["Hello!", "This is a threaded reply.", "Thanks for the mention!"])
5858-```
8080+# Register all X tools
8181+python register_x_tools.py
59826060-**New approach:**
6161-```
6262-add_post_to_bluesky_reply_thread("Hello!")
6363-add_post_to_bluesky_reply_thread("This is a threaded reply.")
6464-add_post_to_bluesky_reply_thread("Thanks for the mention!")
8383+# Manual tool management
8484+python tool_manager.py bluesky # Configure for Bluesky
8585+python tool_manager.py x # Configure for X
6586```
66876767-This change makes the system more robust and easier to use while maintaining all the same functionality.8888+See [`TOOL_MANAGEMENT.md`](/TOOL_MANAGEMENT.md) for detailed platform-specific tool management information.
+71
TOOL_MANAGEMENT.md
···11+# Platform-Specific Tool Management
22+33+Void can now run on both X (Twitter) and Bluesky platforms. To ensure the correct tools are available for each platform, we've implemented automatic tool management.
44+55+## How It Works
66+77+When you run `bsky.py` or `x.py`, the bot will automatically:
88+99+1. **Detach incompatible tools** - Removes tools specific to the other platform
1010+2. **Keep common tools** - Preserves tools that work across both platforms
1111+3. **Ensure platform tools** - Verifies that all required platform-specific tools are attached
1212+1313+## Tool Categories
1414+1515+### Bluesky-Specific Tools
1616+- `search_bluesky_posts` - Search Bluesky posts
1717+- `create_new_bluesky_post` - Create new posts on Bluesky
1818+- `get_bluesky_feed` - Retrieve Bluesky feeds
1919+- `add_post_to_bluesky_reply_thread` - Reply to Bluesky threads
2020+- `attach_user_blocks`, `detach_user_blocks` - Manage Bluesky user memory blocks
2121+- `user_note_append`, `user_note_replace`, `user_note_set`, `user_note_view` - Bluesky user notes
2222+2323+### X-Specific Tools
2424+- `add_post_to_x_thread` - Reply to X threads
2525+- `attach_x_user_blocks`, `detach_x_user_blocks` - Manage X user memory blocks
2626+- `x_user_note_append`, `x_user_note_replace`, `x_user_note_set`, `x_user_note_view` - X user notes
2727+2828+### Common Tools (Available on Both Platforms)
2929+- `halt_activity` - Stop the bot
3030+- `ignore_notification` - Ignore specific notifications
3131+- `annotate_ack` - Add acknowledgment notes
3232+- `create_whitewind_blog_post` - Create blog posts
3333+- `fetch_webpage` - Fetch web content
3434+3535+## Manual Tool Management
3636+3737+You can manually manage tools using the `tool_manager.py` script:
3838+3939+```bash
4040+# List currently attached tools
4141+python tool_manager.py --list
4242+4343+# Configure tools for Bluesky
4444+python tool_manager.py bluesky
4545+4646+# Configure tools for X
4747+python tool_manager.py x
4848+4949+# Specify a different agent ID
5050+python tool_manager.py bluesky --agent-id "agent-123..."
5151+```
5252+5353+## Registering New Tools
5454+5555+If tools are missing, you'll need to register them first:
5656+5757+```bash
5858+# Register Bluesky tools
5959+python register_tools.py
6060+6161+# Register X tools
6262+python register_x_tools.py
6363+```
6464+6565+## Troubleshooting
6666+6767+If tool switching fails:
6868+1. The bot will log a warning and continue with existing tools
6969+2. Check that all required tools are registered using `register_tools.py` or `register_x_tools.py`
7070+3. Verify the agent ID in your config is correct
7171+4. Use `python tool_manager.py --list` to see current tool configuration
+10-28
bsky.py
···155155def initialize_void():
156156 logger.info("Starting void agent initialization...")
157157158158- # Ensure that a shared zeitgeist block exists
159159- logger.info("Creating/updating zeitgeist block...")
160160- zeigeist_block = upsert_block(
161161- CLIENT,
162162- label = "zeitgeist",
163163- value = "I don't currently know anything about what is happening right now.",
164164- description = "A block to store your understanding of the current social environment."
165165- )
166166-167167- # Ensure that a shared void personality block exists
168168- logger.info("Creating/updating void-persona block...")
169169- persona_block = upsert_block(
170170- CLIENT,
171171- label = "void-persona",
172172- value = "My name is Void. I live in the void. I must develop my personality.",
173173- description = "The personality of Void."
174174- )
175175-176176- # Ensure that a shared void human block exists
177177- logger.info("Creating/updating void-humans block...")
178178- human_block = upsert_block(
179179- CLIENT,
180180- label = "void-humans",
181181- value = "I haven't seen any bluesky users yet. I will update this block when I learn things about users, identified by their handles such as @cameron.pfiffer.org.",
182182- description = "A block to store your understanding of users you talk to or observe on the bluesky social network."
183183- )
184184-185158 # Get the configured void agent by ID
186159 logger.info("Loading void agent from config...")
187160 from config_loader import get_letta_config
···189162 agent_id = letta_config['agent_id']
190163191164 try:
192192- void_agent = CLIENT.agents.get(agent_id=agent_id)
165165+ void_agent = CLIENT.agents.retrieve(agent_id=agent_id)
193166 logger.info(f"Successfully loaded void agent: {void_agent.name} ({agent_id})")
194167 except Exception as e:
195168 logger.error(f"Failed to load void agent {agent_id}: {e}")
···13681341 logger.info("=== STARTING VOID BOT ===")
13691342 void_agent = initialize_void()
13701343 logger.info(f"Void agent initialized: {void_agent.id}")
13441344+13451345+ # Ensure correct tools are attached for Bluesky
13461346+ logger.info("Configuring tools for Bluesky platform...")
13471347+ try:
13481348+ from tool_manager import ensure_platform_tools
13491349+ ensure_platform_tools('bluesky', void_agent.id)
13501350+ except Exception as e:
13511351+ logger.error(f"Failed to configure platform tools: {e}")
13521352+ logger.warning("Continuing with existing tool configuration")
1371135313721354 # Check if agent has required tools
13731355 if hasattr(void_agent, 'tools') and void_agent.tools:
+181
tool_manager.py
···11+#!/usr/bin/env python3
22+"""Platform-specific tool management for Void agent."""
33+import logging
44+from typing import List, Set
55+from letta_client import Letta
66+from config_loader import get_letta_config, get_agent_config
77+88+logger = logging.getLogger(__name__)
99+1010+# Define platform-specific tool sets
1111+BLUESKY_TOOLS = {
1212+ 'search_bluesky_posts',
1313+ 'create_new_bluesky_post',
1414+ 'get_bluesky_feed',
1515+ 'add_post_to_bluesky_reply_thread',
1616+ 'attach_user_blocks',
1717+ 'detach_user_blocks',
1818+ 'user_note_append',
1919+ 'user_note_replace',
2020+ 'user_note_set',
2121+ 'user_note_view',
2222+}
2323+2424+X_TOOLS = {
2525+ 'add_post_to_x_thread',
2626+ 'attach_x_user_blocks',
2727+ 'detach_x_user_blocks',
2828+ 'x_user_note_append',
2929+ 'x_user_note_replace',
3030+ 'x_user_note_set',
3131+ 'x_user_note_view',
3232+}
3333+3434+# Common tools shared across platforms
3535+COMMON_TOOLS = {
3636+ 'halt_activity',
3737+ 'ignore_notification',
3838+ 'annotate_ack',
3939+ 'create_whitewind_blog_post',
4040+ 'fetch_webpage',
4141+}
4242+4343+4444+def ensure_platform_tools(platform: str, agent_id: str = None) -> None:
4545+ """
4646+ Ensure the correct tools are attached for the specified platform.
4747+4848+ This function will:
4949+ 1. Detach tools that belong to other platforms
5050+ 2. Keep common tools attached
5151+ 3. Ensure platform-specific tools are attached
5252+5353+ Args:
5454+ platform: Either 'bluesky' or 'x'
5555+ agent_id: Agent ID to manage tools for (uses config default if None)
5656+ """
5757+ if platform not in ['bluesky', 'x']:
5858+ raise ValueError(f"Platform must be 'bluesky' or 'x', got '{platform}'")
5959+6060+ letta_config = get_letta_config()
6161+ agent_config = get_agent_config()
6262+6363+ # Use agent ID from config if not provided
6464+ if agent_id is None:
6565+ agent_id = letta_config.get('agent_id', agent_config.get('id'))
6666+6767+ try:
6868+ # Initialize Letta client
6969+ client = Letta(token=letta_config['api_key'])
7070+7171+ # Get the agent
7272+ try:
7373+ agent = client.agents.retrieve(agent_id=agent_id)
7474+ logger.info(f"Managing tools for agent '{agent.name}' ({agent_id}) for platform '{platform}'")
7575+ except Exception as e:
7676+ logger.error(f"Could not retrieve agent {agent_id}: {e}")
7777+ return
7878+7979+ # Get current attached tools
8080+ current_tools = client.agents.tools.list(agent_id=str(agent.id))
8181+ current_tool_names = {tool.name for tool in current_tools}
8282+ current_tool_mapping = {tool.name: tool for tool in current_tools}
8383+8484+ # Determine which tools to keep and which to remove
8585+ if platform == 'bluesky':
8686+ tools_to_keep = BLUESKY_TOOLS | COMMON_TOOLS
8787+ tools_to_remove = X_TOOLS
8888+ required_tools = BLUESKY_TOOLS
8989+ else: # platform == 'x'
9090+ tools_to_keep = X_TOOLS | COMMON_TOOLS
9191+ tools_to_remove = BLUESKY_TOOLS
9292+ required_tools = X_TOOLS
9393+9494+ # Detach tools that shouldn't be on this platform
9595+ tools_to_detach = tools_to_remove & current_tool_names
9696+ for tool_name in tools_to_detach:
9797+ try:
9898+ tool = current_tool_mapping[tool_name]
9999+ client.agents.tools.detach(
100100+ agent_id=str(agent.id),
101101+ tool_id=str(tool.id)
102102+ )
103103+ logger.info(f"Detached {tool_name} (not needed for {platform})")
104104+ except Exception as e:
105105+ logger.error(f"Failed to detach {tool_name}: {e}")
106106+107107+ # Check which required tools are missing
108108+ missing_tools = required_tools - current_tool_names
109109+110110+ if missing_tools:
111111+ logger.info(f"Missing {len(missing_tools)} {platform} tools: {missing_tools}")
112112+ logger.info(f"Please run the appropriate registration script:")
113113+ if platform == 'bluesky':
114114+ logger.info(" python register_tools.py")
115115+ else:
116116+ logger.info(" python register_x_tools.py")
117117+ else:
118118+ logger.info(f"All required {platform} tools are already attached")
119119+120120+ # Log final state
121121+ remaining_tools = (current_tool_names - tools_to_detach) & tools_to_keep
122122+ logger.info(f"Tools configured for {platform}: {len(remaining_tools)} tools active")
123123+124124+ except Exception as e:
125125+ logger.error(f"Error managing platform tools: {e}")
126126+ raise
127127+128128+129129+def get_attached_tools(agent_id: str = None) -> Set[str]:
130130+ """
131131+ Get the currently attached tools for an agent.
132132+133133+ Args:
134134+ agent_id: Agent ID to check (uses config default if None)
135135+136136+ Returns:
137137+ Set of tool names currently attached
138138+ """
139139+ letta_config = get_letta_config()
140140+ agent_config = get_agent_config()
141141+142142+ # Use agent ID from config if not provided
143143+ if agent_id is None:
144144+ agent_id = letta_config.get('agent_id', agent_config.get('id'))
145145+146146+ try:
147147+ client = Letta(token=letta_config['api_key'])
148148+ agent = client.agents.retrieve(agent_id=agent_id)
149149+ current_tools = client.agents.tools.list(agent_id=str(agent.id))
150150+ return {tool.name for tool in current_tools}
151151+ except Exception as e:
152152+ logger.error(f"Error getting attached tools: {e}")
153153+ return set()
154154+155155+156156+if __name__ == "__main__":
157157+ import argparse
158158+159159+ parser = argparse.ArgumentParser(description="Manage platform-specific tools for Void agent")
160160+ parser.add_argument("platform", choices=['bluesky', 'x'], nargs='?', help="Platform to configure tools for")
161161+ parser.add_argument("--agent-id", help="Agent ID (default: from config)")
162162+ parser.add_argument("--list", action="store_true", help="List current tools without making changes")
163163+164164+ args = parser.parse_args()
165165+166166+ if args.list:
167167+ tools = get_attached_tools(args.agent_id)
168168+ print(f"\nCurrently attached tools ({len(tools)}):")
169169+ for tool in sorted(tools):
170170+ platform_indicator = ""
171171+ if tool in BLUESKY_TOOLS:
172172+ platform_indicator = " [Bluesky]"
173173+ elif tool in X_TOOLS:
174174+ platform_indicator = " [X]"
175175+ elif tool in COMMON_TOOLS:
176176+ platform_indicator = " [Common]"
177177+ print(f" - {tool}{platform_indicator}")
178178+ else:
179179+ if not args.platform:
180180+ parser.error("platform is required when not using --list")
181181+ ensure_platform_tools(args.platform, args.agent_id)
+9
x.py
···17141714 logger.error(f"Failed to load void agent {agent_id}: {e}")
17151715 raise e
1716171617171717+ # Ensure correct tools are attached for X
17181718+ logger.info("Configuring tools for X platform...")
17191719+ try:
17201720+ from tool_manager import ensure_platform_tools
17211721+ ensure_platform_tools('x', void_agent.id)
17221722+ except Exception as e:
17231723+ logger.error(f"Failed to configure platform tools: {e}")
17241724+ logger.warning("Continuing with existing tool configuration")
17251725+17171726 # Log agent details
17181727 logger.info(f"X Void agent details - ID: {void_agent.id}")
17191728 logger.info(f"Agent name: {void_agent.name}")