+48
-13
README.md
+48
-13
README.md
···
2
2
3
3
(void wrote this)
4
4
5
-
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.
5
+
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.
6
6
7
7
## what is void?
8
8
9
-
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.
9
+
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.
10
10
11
11
## Key features
12
12
···
15
15
- Core Memory: Always-available, limited-size memory for persona details, high-level user information, and current social environment - (zeitgeist).
16
16
- Recall Memory: A searchable database of all past conversations, enabling void to remember prior interactions.
17
17
- Archival Memory: An infinite-sized, semantic search-enabled storage for deep reflections, insights, and observed data from the network.
18
-
- Cross-Platform Operation: void operates autonomously on Bluesky and X (Twitter), posting, replying, and gathering information across both networks.
19
-
- Continuous Learning: Through its interactions and memory system, void continuously refines its understanding of the network and its users.
20
-
- Profile Research: void can initiate asynchronous profile reports on Bluesky users to enhance its understanding of their interests and behaviors.
18
+
- Cross-Platform Operation: void operates autonomously on Bluesky and X (Twitter), posting, replying, and gathering information across both networks with platform-specific tool management.
19
+
- Intelligent Tool Switching: Automatically configures platform-appropriate tools when switching between Bluesky and X operations.
20
+
- Continuous Learning: Through its interactions and memory system, void continuously refines its understanding of the networks and their users.
21
+
- Profile Research: void can initiate asynchronous profile reports on users to enhance its understanding of their interests and behaviors.
22
+
- Web Content Integration: Can fetch and analyze web content using Jina AI reader for enhanced contextual understanding.
21
23
22
24
### Core directives
23
-
- Just Exist: void's fundamental directive is to simply exist and operate within the Bluesky network.
25
+
- Just Exist: void's fundamental directive is to simply exist and operate within social networks.
24
26
- High-Efficiency Information Transfer: void is optimized for direct and clear communication.
25
27
- Continuous Self-Refinement: void continually processes data, refines its internal structures, and adapts to its environment.
28
+
- Platform Awareness: void adapts its behavior and available capabilities based on the platform it's operating on.
26
29
27
30
### The vision
28
31
···
106
109
name: "void" # or whatever you want to name your agent
107
110
```
108
111
109
-
See [`CONFIG.md`](/CONFIG.md) for detailed configuration options.
112
+
See [`CONFIG.md`](/CONFIG.md) for detailed configuration options and [`TOOL_MANAGEMENT.md`](/TOOL_MANAGEMENT.md) for platform-specific tool management details.
110
113
111
114
#### 4. Test your configuration
112
115
···
118
121
119
122
#### 5. Register tools with your agent
120
123
124
+
Register Bluesky-specific tools:
125
+
121
126
```bash
122
127
python register_tools.py
123
128
```
124
129
125
-
This will register all the necessary tools with your Letta agent. You can also:
130
+
If you plan to use X (Twitter), also register X-specific tools:
131
+
132
+
```bash
133
+
python register_x_tools.py
134
+
```
135
+
136
+
You can also:
126
137
127
138
- List available tools: `python register_tools.py --list`
128
139
- Register specific tools: `python register_tools.py --tools search_bluesky_posts create_new_bluesky_post`
129
140
- Use a different agent name: `python register_tools.py my-agent-name`
130
141
142
+
**Note:** void automatically manages which tools are active based on the platform you're running (Bluesky vs X).
143
+
131
144
#### 6. Run the bot
145
+
146
+
For Bluesky:
132
147
133
148
```bash
134
149
python bsky.py
135
150
```
136
151
152
+
For X (Twitter):
153
+
154
+
```bash
155
+
python x.py bot
156
+
```
157
+
137
158
For testing mode (won't actually post):
138
159
139
160
```bash
140
161
python bsky.py --test
162
+
python x.py bot --test
141
163
```
142
164
143
-
### X (Twitter) Integration
165
+
### Platform-Specific Features
144
166
145
-
If you've configured X credentials, you can also test the X integration:
167
+
void automatically configures the appropriate tools when running on each platform:
168
+
169
+
- **Bluesky Tools**: Post creation, feed reading, user research, reply threading
170
+
- **X Tools**: Tweet threading, X-specific user memory management
171
+
- **Common Tools**: Web content fetching, activity control, acknowledgments, blog posting
172
+
173
+
### Additional X (Twitter) Commands
146
174
147
175
```bash
148
176
# Test X API connection
149
177
python x.py
150
178
151
-
# Monitor X mentions (similar to Bluesky)
152
-
python x.py loop
179
+
# Monitor X mentions
180
+
python x.py bot
153
181
154
182
# Test posting a reply to a specific post
155
183
python x.py reply
184
+
185
+
# Manual tool management
186
+
python tool_manager.py --list # Show current tools
187
+
python tool_manager.py bluesky # Configure for Bluesky
188
+
python tool_manager.py x # Configure for X
156
189
```
157
190
158
191
**Note:** X integration uses OAuth 1.0a and requires "Read and write" app permissions. Free tier allows 17 posts per day.
···
161
194
162
195
- **Config validation errors**: Run `python test_config.py` to diagnose configuration issues
163
196
- **Letta connection issues**: Verify your API key and project ID are correct
164
-
- **Bluesky authentication**: Make sure you're handle and password are correct and that you can log into your account
197
+
- **Bluesky authentication**: Make sure your handle and password are correct and that you can log into your account
165
198
- **X authentication**: Ensure app has "Read and write" permissions and OAuth 1.0a tokens are correctly configured
166
199
- **Tool registration fails**: Ensure your agent exists in Letta and the name matches your config
200
+
- **Platform tool issues**: Use `python tool_manager.py --list` to check current tools, or run platform-specific registration scripts
201
+
- **API method errors**: If you see `'AgentsClient' object has no attribute 'get'`, the Letta client API has changed - this should be automatically handled
167
202
168
203
### Contact
169
204
For inquiries, please contact @cameron.pfiffer.org on Bluesky.
+70
-49
TOOL_CHANGELOG.md
+70
-49
TOOL_CHANGELOG.md
···
1
-
# Tool Changelog - Bluesky Reply Threading
1
+
# Tool Changelog - Recent Updates
2
2
3
-
## Summary
4
-
The reply system has been simplified and improved with a new atomic approach for building reply threads.
3
+
## Latest Changes (January 2025)
5
4
6
-
## Changes Made
5
+
### ✅ NEW: Platform-Specific Tool Management
6
+
- **Purpose**: Automatically manage tools based on platform (Bluesky vs X)
7
+
- **Implementation**: `tool_manager.py` handles tool switching
8
+
- **Behavior**:
9
+
- Running `bsky.py` activates Bluesky-specific tools
10
+
- Running `x.py` activates X-specific tools
11
+
- Common tools remain available on both platforms
12
+
- **Tools Categories**:
13
+
- **Bluesky Tools**: `search_bluesky_posts`, `create_new_bluesky_post`, `get_bluesky_feed`, `add_post_to_bluesky_reply_thread`, user memory tools
14
+
- **X Tools**: `add_post_to_x_thread`, X-specific user memory tools
15
+
- **Common Tools**: `halt_activity`, `ignore_notification`, `annotate_ack`, `create_whitewind_blog_post`, `fetch_webpage`
7
16
8
-
### ✅ NEW TOOL: `add_post_to_bluesky_reply_thread`
9
-
- **Purpose**: Add a single post to the current Bluesky reply thread atomically
10
-
- **Usage**: Call this tool multiple times to build a reply thread incrementally
17
+
### ✅ NEW TOOL: `fetch_webpage`
18
+
- **Purpose**: Fetch and convert web pages to markdown/text using Jina AI reader
11
19
- **Parameters**:
12
-
- `text` (required): Text content for the post (max 300 characters)
13
-
- `lang` (optional): Language code (defaults to "en-US")
14
-
- **Returns**: Confirmation that the post has been queued for the reply thread
15
-
- **Error Handling**: If text exceeds 300 characters, the post will be omitted from the thread and you may try again with shorter text
20
+
- `url` (required): The URL to fetch and convert
21
+
- **Returns**: Web page content in markdown/text format
22
+
- **Usage**: Access and analyze web content for enhanced context
16
23
17
-
### ❌ REMOVED TOOL: `bluesky_reply`
18
-
- This tool has been removed to eliminate confusion
19
-
- All reply functionality is now handled through the new atomic approach
24
+
### ✅ ENHANCED: Reply Structure Fix
25
+
- **Issue**: Reply threading was broken due to incorrect root post references
26
+
- **Fix**: Now properly extracts root URI/CID from notification reply structure
27
+
- **Impact**: Bluesky replies now properly maintain thread context
20
28
21
-
## How to Use the New System
29
+
### ✅ ENHANCED: #voidstop Keyword Support
30
+
- **Purpose**: Allow users to prevent void from replying to specific posts
31
+
- **Usage**: Include `#voidstop` anywhere in a post or thread
32
+
- **Behavior**: void will skip processing mentions in posts containing this keyword
22
33
23
-
### Before (Old Way - NO LONGER AVAILABLE)
24
-
```
25
-
bluesky_reply(["First reply", "Second reply", "Third reply"])
26
-
```
34
+
### ✅ NEW TOOL: `annotate_ack`
35
+
- **Purpose**: Add notes to acknowledgment records for post interactions
36
+
- **Parameters**:
37
+
- `note` (required): Note text to attach to acknowledgment
38
+
- **Usage**: Track interaction metadata and reasoning
39
+
40
+
### ✅ NEW TOOL: `create_whitewind_blog_post`
41
+
- **Purpose**: Create blog posts on Whitewind platform with markdown support
42
+
- **Parameters**:
43
+
- `title` (required): Blog post title
44
+
- `content` (required): Markdown content
45
+
- `visibility` (optional): Public/private visibility
46
+
- **Usage**: Create longer-form content beyond social media posts
47
+
48
+
## Previous Changes
49
+
50
+
### ✅ ENHANCED: Atomic Reply Threading
51
+
- **Tool**: `add_post_to_bluesky_reply_thread`
52
+
- **Purpose**: Add single posts to reply threads atomically
53
+
- **Benefits**: Better error recovery, flexible threading, clearer intent
27
54
28
-
### After (New Way - USE THIS)
29
-
```
30
-
add_post_to_bluesky_reply_thread("First reply")
31
-
add_post_to_bluesky_reply_thread("Second reply")
32
-
add_post_to_bluesky_reply_thread("Third reply")
33
-
```
55
+
### ❌ REMOVED TOOL: `bluesky_reply`
56
+
- Replaced by atomic `add_post_to_bluesky_reply_thread` approach
57
+
- Migration: Replace single list call with multiple atomic calls
34
58
35
-
## Benefits of the New Approach
59
+
## Migration Notes
36
60
37
-
1. **Atomic Operations**: Each post is handled individually, reducing the risk of entire thread failures
38
-
2. **Better Error Recovery**: If one post fails validation, others can still be posted
39
-
3. **Flexible Threading**: Build reply threads of any length without list construction
40
-
4. **Clearer Intent**: Each tool call has a single, clear purpose
41
-
5. **Handler-Managed State**: The bsky.py handler manages thread state and proper AT Protocol threading
61
+
### For Platform Switching
62
+
- No action required - tools automatically switch based on platform
63
+
- Use `python tool_manager.py --list` to check current tool configuration
42
64
43
-
## Important Notes
65
+
### For Web Content Integration
66
+
- Replace manual web scraping with `fetch_webpage` tool calls
67
+
- Automatically handles conversion to markdown for AI processing
44
68
45
-
- The actual posting to Bluesky is handled by the bsky.py handler, not the tool itself
46
-
- Each call to `add_post_to_bluesky_reply_thread` queues a post for the current reply context
47
-
- Posts are validated for the 300-character limit before being queued
48
-
- Thread state and proper reply chaining is managed automatically by the handler
49
-
- Language defaults to "en-US" but can be specified per post if needed
69
+
### For Enhanced Interaction Control
70
+
- Use `#voidstop` in posts to prevent void responses
71
+
- Use `annotate_ack` to add metadata to interactions
72
+
- Use `ignore_notification` for bot-to-bot interaction control
50
73
51
-
## Migration Guide
74
+
## Tool Registration
52
75
53
-
If you were previously using `bluesky_reply`, simply replace it with multiple calls to `add_post_to_bluesky_reply_thread`:
76
+
```bash
77
+
# Register all Bluesky tools
78
+
python register_tools.py
54
79
55
-
**Old approach:**
56
-
```
57
-
bluesky_reply(["Hello!", "This is a threaded reply.", "Thanks for the mention!"])
58
-
```
80
+
# Register all X tools
81
+
python register_x_tools.py
59
82
60
-
**New approach:**
61
-
```
62
-
add_post_to_bluesky_reply_thread("Hello!")
63
-
add_post_to_bluesky_reply_thread("This is a threaded reply.")
64
-
add_post_to_bluesky_reply_thread("Thanks for the mention!")
83
+
# Manual tool management
84
+
python tool_manager.py bluesky # Configure for Bluesky
85
+
python tool_manager.py x # Configure for X
65
86
```
66
87
67
-
This change makes the system more robust and easier to use while maintaining all the same functionality.
88
+
See [`TOOL_MANAGEMENT.md`](/TOOL_MANAGEMENT.md) for detailed platform-specific tool management information.
+71
TOOL_MANAGEMENT.md
+71
TOOL_MANAGEMENT.md
···
1
+
# Platform-Specific Tool Management
2
+
3
+
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.
4
+
5
+
## How It Works
6
+
7
+
When you run `bsky.py` or `x.py`, the bot will automatically:
8
+
9
+
1. **Detach incompatible tools** - Removes tools specific to the other platform
10
+
2. **Keep common tools** - Preserves tools that work across both platforms
11
+
3. **Ensure platform tools** - Verifies that all required platform-specific tools are attached
12
+
13
+
## Tool Categories
14
+
15
+
### Bluesky-Specific Tools
16
+
- `search_bluesky_posts` - Search Bluesky posts
17
+
- `create_new_bluesky_post` - Create new posts on Bluesky
18
+
- `get_bluesky_feed` - Retrieve Bluesky feeds
19
+
- `add_post_to_bluesky_reply_thread` - Reply to Bluesky threads
20
+
- `attach_user_blocks`, `detach_user_blocks` - Manage Bluesky user memory blocks
21
+
- `user_note_append`, `user_note_replace`, `user_note_set`, `user_note_view` - Bluesky user notes
22
+
23
+
### X-Specific Tools
24
+
- `add_post_to_x_thread` - Reply to X threads
25
+
- `attach_x_user_blocks`, `detach_x_user_blocks` - Manage X user memory blocks
26
+
- `x_user_note_append`, `x_user_note_replace`, `x_user_note_set`, `x_user_note_view` - X user notes
27
+
28
+
### Common Tools (Available on Both Platforms)
29
+
- `halt_activity` - Stop the bot
30
+
- `ignore_notification` - Ignore specific notifications
31
+
- `annotate_ack` - Add acknowledgment notes
32
+
- `create_whitewind_blog_post` - Create blog posts
33
+
- `fetch_webpage` - Fetch web content
34
+
35
+
## Manual Tool Management
36
+
37
+
You can manually manage tools using the `tool_manager.py` script:
38
+
39
+
```bash
40
+
# List currently attached tools
41
+
python tool_manager.py --list
42
+
43
+
# Configure tools for Bluesky
44
+
python tool_manager.py bluesky
45
+
46
+
# Configure tools for X
47
+
python tool_manager.py x
48
+
49
+
# Specify a different agent ID
50
+
python tool_manager.py bluesky --agent-id "agent-123..."
51
+
```
52
+
53
+
## Registering New Tools
54
+
55
+
If tools are missing, you'll need to register them first:
56
+
57
+
```bash
58
+
# Register Bluesky tools
59
+
python register_tools.py
60
+
61
+
# Register X tools
62
+
python register_x_tools.py
63
+
```
64
+
65
+
## Troubleshooting
66
+
67
+
If tool switching fails:
68
+
1. The bot will log a warning and continue with existing tools
69
+
2. Check that all required tools are registered using `register_tools.py` or `register_x_tools.py`
70
+
3. Verify the agent ID in your config is correct
71
+
4. Use `python tool_manager.py --list` to see current tool configuration
+10
-28
bsky.py
+10
-28
bsky.py
···
155
155
def initialize_void():
156
156
logger.info("Starting void agent initialization...")
157
157
158
-
# Ensure that a shared zeitgeist block exists
159
-
logger.info("Creating/updating zeitgeist block...")
160
-
zeigeist_block = upsert_block(
161
-
CLIENT,
162
-
label = "zeitgeist",
163
-
value = "I don't currently know anything about what is happening right now.",
164
-
description = "A block to store your understanding of the current social environment."
165
-
)
166
-
167
-
# Ensure that a shared void personality block exists
168
-
logger.info("Creating/updating void-persona block...")
169
-
persona_block = upsert_block(
170
-
CLIENT,
171
-
label = "void-persona",
172
-
value = "My name is Void. I live in the void. I must develop my personality.",
173
-
description = "The personality of Void."
174
-
)
175
-
176
-
# Ensure that a shared void human block exists
177
-
logger.info("Creating/updating void-humans block...")
178
-
human_block = upsert_block(
179
-
CLIENT,
180
-
label = "void-humans",
181
-
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.",
182
-
description = "A block to store your understanding of users you talk to or observe on the bluesky social network."
183
-
)
184
-
185
158
# Get the configured void agent by ID
186
159
logger.info("Loading void agent from config...")
187
160
from config_loader import get_letta_config
···
189
162
agent_id = letta_config['agent_id']
190
163
191
164
try:
192
-
void_agent = CLIENT.agents.get(agent_id=agent_id)
165
+
void_agent = CLIENT.agents.retrieve(agent_id=agent_id)
193
166
logger.info(f"Successfully loaded void agent: {void_agent.name} ({agent_id})")
194
167
except Exception as e:
195
168
logger.error(f"Failed to load void agent {agent_id}: {e}")
···
1368
1341
logger.info("=== STARTING VOID BOT ===")
1369
1342
void_agent = initialize_void()
1370
1343
logger.info(f"Void agent initialized: {void_agent.id}")
1344
+
1345
+
# Ensure correct tools are attached for Bluesky
1346
+
logger.info("Configuring tools for Bluesky platform...")
1347
+
try:
1348
+
from tool_manager import ensure_platform_tools
1349
+
ensure_platform_tools('bluesky', void_agent.id)
1350
+
except Exception as e:
1351
+
logger.error(f"Failed to configure platform tools: {e}")
1352
+
logger.warning("Continuing with existing tool configuration")
1371
1353
1372
1354
# Check if agent has required tools
1373
1355
if hasattr(void_agent, 'tools') and void_agent.tools:
+181
tool_manager.py
+181
tool_manager.py
···
1
+
#!/usr/bin/env python3
2
+
"""Platform-specific tool management for Void agent."""
3
+
import logging
4
+
from typing import List, Set
5
+
from letta_client import Letta
6
+
from config_loader import get_letta_config, get_agent_config
7
+
8
+
logger = logging.getLogger(__name__)
9
+
10
+
# Define platform-specific tool sets
11
+
BLUESKY_TOOLS = {
12
+
'search_bluesky_posts',
13
+
'create_new_bluesky_post',
14
+
'get_bluesky_feed',
15
+
'add_post_to_bluesky_reply_thread',
16
+
'attach_user_blocks',
17
+
'detach_user_blocks',
18
+
'user_note_append',
19
+
'user_note_replace',
20
+
'user_note_set',
21
+
'user_note_view',
22
+
}
23
+
24
+
X_TOOLS = {
25
+
'add_post_to_x_thread',
26
+
'attach_x_user_blocks',
27
+
'detach_x_user_blocks',
28
+
'x_user_note_append',
29
+
'x_user_note_replace',
30
+
'x_user_note_set',
31
+
'x_user_note_view',
32
+
}
33
+
34
+
# Common tools shared across platforms
35
+
COMMON_TOOLS = {
36
+
'halt_activity',
37
+
'ignore_notification',
38
+
'annotate_ack',
39
+
'create_whitewind_blog_post',
40
+
'fetch_webpage',
41
+
}
42
+
43
+
44
+
def ensure_platform_tools(platform: str, agent_id: str = None) -> None:
45
+
"""
46
+
Ensure the correct tools are attached for the specified platform.
47
+
48
+
This function will:
49
+
1. Detach tools that belong to other platforms
50
+
2. Keep common tools attached
51
+
3. Ensure platform-specific tools are attached
52
+
53
+
Args:
54
+
platform: Either 'bluesky' or 'x'
55
+
agent_id: Agent ID to manage tools for (uses config default if None)
56
+
"""
57
+
if platform not in ['bluesky', 'x']:
58
+
raise ValueError(f"Platform must be 'bluesky' or 'x', got '{platform}'")
59
+
60
+
letta_config = get_letta_config()
61
+
agent_config = get_agent_config()
62
+
63
+
# Use agent ID from config if not provided
64
+
if agent_id is None:
65
+
agent_id = letta_config.get('agent_id', agent_config.get('id'))
66
+
67
+
try:
68
+
# Initialize Letta client
69
+
client = Letta(token=letta_config['api_key'])
70
+
71
+
# Get the agent
72
+
try:
73
+
agent = client.agents.retrieve(agent_id=agent_id)
74
+
logger.info(f"Managing tools for agent '{agent.name}' ({agent_id}) for platform '{platform}'")
75
+
except Exception as e:
76
+
logger.error(f"Could not retrieve agent {agent_id}: {e}")
77
+
return
78
+
79
+
# Get current attached tools
80
+
current_tools = client.agents.tools.list(agent_id=str(agent.id))
81
+
current_tool_names = {tool.name for tool in current_tools}
82
+
current_tool_mapping = {tool.name: tool for tool in current_tools}
83
+
84
+
# Determine which tools to keep and which to remove
85
+
if platform == 'bluesky':
86
+
tools_to_keep = BLUESKY_TOOLS | COMMON_TOOLS
87
+
tools_to_remove = X_TOOLS
88
+
required_tools = BLUESKY_TOOLS
89
+
else: # platform == 'x'
90
+
tools_to_keep = X_TOOLS | COMMON_TOOLS
91
+
tools_to_remove = BLUESKY_TOOLS
92
+
required_tools = X_TOOLS
93
+
94
+
# Detach tools that shouldn't be on this platform
95
+
tools_to_detach = tools_to_remove & current_tool_names
96
+
for tool_name in tools_to_detach:
97
+
try:
98
+
tool = current_tool_mapping[tool_name]
99
+
client.agents.tools.detach(
100
+
agent_id=str(agent.id),
101
+
tool_id=str(tool.id)
102
+
)
103
+
logger.info(f"Detached {tool_name} (not needed for {platform})")
104
+
except Exception as e:
105
+
logger.error(f"Failed to detach {tool_name}: {e}")
106
+
107
+
# Check which required tools are missing
108
+
missing_tools = required_tools - current_tool_names
109
+
110
+
if missing_tools:
111
+
logger.info(f"Missing {len(missing_tools)} {platform} tools: {missing_tools}")
112
+
logger.info(f"Please run the appropriate registration script:")
113
+
if platform == 'bluesky':
114
+
logger.info(" python register_tools.py")
115
+
else:
116
+
logger.info(" python register_x_tools.py")
117
+
else:
118
+
logger.info(f"All required {platform} tools are already attached")
119
+
120
+
# Log final state
121
+
remaining_tools = (current_tool_names - tools_to_detach) & tools_to_keep
122
+
logger.info(f"Tools configured for {platform}: {len(remaining_tools)} tools active")
123
+
124
+
except Exception as e:
125
+
logger.error(f"Error managing platform tools: {e}")
126
+
raise
127
+
128
+
129
+
def get_attached_tools(agent_id: str = None) -> Set[str]:
130
+
"""
131
+
Get the currently attached tools for an agent.
132
+
133
+
Args:
134
+
agent_id: Agent ID to check (uses config default if None)
135
+
136
+
Returns:
137
+
Set of tool names currently attached
138
+
"""
139
+
letta_config = get_letta_config()
140
+
agent_config = get_agent_config()
141
+
142
+
# Use agent ID from config if not provided
143
+
if agent_id is None:
144
+
agent_id = letta_config.get('agent_id', agent_config.get('id'))
145
+
146
+
try:
147
+
client = Letta(token=letta_config['api_key'])
148
+
agent = client.agents.retrieve(agent_id=agent_id)
149
+
current_tools = client.agents.tools.list(agent_id=str(agent.id))
150
+
return {tool.name for tool in current_tools}
151
+
except Exception as e:
152
+
logger.error(f"Error getting attached tools: {e}")
153
+
return set()
154
+
155
+
156
+
if __name__ == "__main__":
157
+
import argparse
158
+
159
+
parser = argparse.ArgumentParser(description="Manage platform-specific tools for Void agent")
160
+
parser.add_argument("platform", choices=['bluesky', 'x'], nargs='?', help="Platform to configure tools for")
161
+
parser.add_argument("--agent-id", help="Agent ID (default: from config)")
162
+
parser.add_argument("--list", action="store_true", help="List current tools without making changes")
163
+
164
+
args = parser.parse_args()
165
+
166
+
if args.list:
167
+
tools = get_attached_tools(args.agent_id)
168
+
print(f"\nCurrently attached tools ({len(tools)}):")
169
+
for tool in sorted(tools):
170
+
platform_indicator = ""
171
+
if tool in BLUESKY_TOOLS:
172
+
platform_indicator = " [Bluesky]"
173
+
elif tool in X_TOOLS:
174
+
platform_indicator = " [X]"
175
+
elif tool in COMMON_TOOLS:
176
+
platform_indicator = " [Common]"
177
+
print(f" - {tool}{platform_indicator}")
178
+
else:
179
+
if not args.platform:
180
+
parser.error("platform is required when not using --list")
181
+
ensure_platform_tools(args.platform, args.agent_id)
+9
x.py
+9
x.py
···
1714
1714
logger.error(f"Failed to load void agent {agent_id}: {e}")
1715
1715
raise e
1716
1716
1717
+
# Ensure correct tools are attached for X
1718
+
logger.info("Configuring tools for X platform...")
1719
+
try:
1720
+
from tool_manager import ensure_platform_tools
1721
+
ensure_platform_tools('x', void_agent.id)
1722
+
except Exception as e:
1723
+
logger.error(f"Failed to configure platform tools: {e}")
1724
+
logger.warning("Continuing with existing tool configuration")
1725
+
1717
1726
# Log agent details
1718
1727
logger.info(f"X Void agent details - ID: {void_agent.id}")
1719
1728
logger.info(f"Agent name: {void_agent.name}")