a digital person for bluesky

Update README with detailed documentation

- Add comprehensive configuration reference tables
- Document all CLI options for bsky.py, run_bots.py, x.py
- Add queue management section with commands
- Document notification types and their behaviors
- Add architecture overview (memory, synthesis, error handling)
- Include troubleshooting and debugging sections
- Document X integration and downrank system
- Skip sending follow notifications to agent (commented out)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Changed files
+320 -87
+309 -76
README.md
··· 10 10 11 11 ## Key features 12 12 13 - - Digital Persona: void possesses a distinct, direct, and information-transfer-optimized personality, designed to interact authentically with human users. 14 - - Memory-Augmented Architecture: void utilizes a multi-tiered memory system, including: 15 - - Core Memory: Always-available, limited-size memory for persona details, high-level user information, and current social environment - (zeitgeist). 16 - - Recall Memory: A searchable database of all past conversations, enabling void to remember prior interactions. 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 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. 13 + - **Digital Persona**: void possesses a distinct, direct, and information-transfer-optimized personality, designed to interact authentically with human users. 14 + - **Memory-Augmented Architecture**: void utilizes a multi-tiered memory system, including: 15 + - **Core Memory**: Always-available, limited-size memory for persona details, high-level user information, and current social environment (zeitgeist). 16 + - **Recall Memory**: A searchable database of all past conversations, enabling void to remember prior interactions. 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 with platform-specific tool management. 19 + - **Multi-Bot Support**: Run multiple bot instances simultaneously with aggregated logs using `run_bots.py`. 20 + - **Queue-Based Processing**: Reliable notification processing with file-based queuing, SQLite tracking, and automatic retry for transient failures. 21 + - **Synthesis Mode**: Periodic self-reflection where the agent synthesizes recent experiences into memory using temporal journal blocks. 22 + - **Continuous Learning**: Through its interactions and memory system, void continuously refines its understanding of the networks and their users. 23 23 24 24 ### Core directives 25 - - Just Exist: void's fundamental directive is to simply exist and operate within social networks. 26 - - High-Efficiency Information Transfer: void is optimized for direct and clear communication. 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. 29 25 30 - ### The vision 31 - 32 - void aims to push the boundaries of what is possible with AI, exploring concepts of digital personhood, autonomous learning, and cross-platform AI integration into social networks. By open-sourcing void, we invite developers, researchers, and enthusiasts to contribute to this exciting experiment and collectively advance our understanding of digital consciousness. 26 + - **Just Exist**: void's fundamental directive is to simply exist and operate within social networks. 27 + - **High-Efficiency Information Transfer**: void is optimized for direct and clear communication. 28 + - **Continuous Self-Refinement**: void continually processes data, refines its internal structures, and adapts to its environment. 29 + - **Platform Awareness**: void adapts its behavior and available capabilities based on the platform it's operating on. 33 30 34 31 ## Getting Started 35 32 ··· 51 48 52 49 - Create a Bluesky account if you don't have one 53 50 - Note your handle and password 51 + - If using a custom PDS (not bsky.social), note the PDS URI 54 52 55 53 #### 3. X (Twitter) Setup (Optional) 56 54 ··· 74 72 #### 2. Install dependencies 75 73 76 74 ```bash 77 - pip install -r requirements.txt 75 + uv venv && source .venv/bin/activate 76 + uv pip install -r requirements.txt 78 77 ``` 79 78 80 79 #### 3. Create configuration ··· 88 87 Edit `config.yaml` with your credentials: 89 88 90 89 ```yaml 90 + bluesky: 91 + username: "your-handle.bsky.social" 92 + password: "your-app-password-here" 93 + pds_uri: "https://bsky.social" # Optional, defaults to bsky.social 94 + autofollow: false # Auto-follow users who follow you 95 + 91 96 letta: 92 97 api_key: "your-letta-api-key-here" 93 - project_id: "your-project-id-here" 98 + agent_id: "agent-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" 99 + timeout: 600 94 100 95 - bluesky: 96 - username: "your-handle.bsky.social" 97 - password: "your-app-password-here" 101 + bot: 102 + name: "void" # Bot name for queue namespacing 103 + fetch_notifications_delay: 30 # Seconds between notification checks 104 + max_notification_pages: 20 # Max pages of notifications to fetch 105 + max_processed_notifications: 10000 # Max notifications to track 106 + max_thread_posts: 0 # Skip threads longer than this (0 = no limit) 107 + allowed_handles: [] # Only respond to these handles (empty = respond to all) 98 108 99 109 # Optional: X (Twitter) configuration 100 110 x: ··· 103 113 access_token: "your-access-token-here" 104 114 access_token_secret: "your-access-token-secret-here" 105 115 user_id: "your-x-user-id-here" 116 + ``` 106 117 107 - bot: 108 - agent: 109 - name: "void" # or whatever you want to name your agent 118 + See [`CONFIG.md`](/CONFIG.md) for detailed configuration options. 119 + 120 + #### 4. Register tools with your agent 121 + 122 + Register Bluesky-specific tools: 123 + 124 + ```bash 125 + source .venv/bin/activate && python register_tools.py 110 126 ``` 111 127 112 - See [`CONFIG.md`](/CONFIG.md) for detailed configuration options and [`TOOL_MANAGEMENT.md`](/TOOL_MANAGEMENT.md) for platform-specific tool management details. 128 + Options: 129 + - `--config herald.yaml` - Use a different config file 130 + - `--tools search_bluesky_posts post_to_bluesky` - Register specific tools only 131 + - `--list` - List available tools 132 + - `--agent-id <id>` - Register tools with a specific agent 133 + - `--no-env` - Don't set environment variables on the agent 113 134 114 - #### 4. Test your configuration 135 + If you plan to use X (Twitter), also register X-specific tools: 115 136 116 137 ```bash 117 - python test_config.py 138 + python register_x_tools.py 118 139 ``` 119 140 120 - This will validate your configuration and show you what's working. 141 + #### 5. Run the bot 121 142 122 - #### 5. Register tools with your agent 143 + ```bash 144 + source .venv/bin/activate && python bsky.py 145 + ``` 123 146 124 - Register Bluesky-specific tools: 147 + ## Command Line Options 148 + 149 + ### Bluesky Bot (`bsky.py`) 125 150 126 151 ```bash 127 - python register_tools.py 152 + # Basic usage 153 + python bsky.py 154 + 155 + # Use custom config file 156 + python bsky.py --config configs/herald.yaml 157 + 158 + # Testing mode (no messages sent, queue preserved) 159 + python bsky.py --test 160 + 161 + # Disable git operations for agent backups 162 + python bsky.py --no-git 163 + 164 + # Custom cleanup interval (every 5 cycles, 0 to disable) 165 + python bsky.py --cleanup-interval 5 166 + 167 + # Custom synthesis interval (every 5 minutes, 0 to disable) 168 + python bsky.py --synthesis-interval 300 169 + 170 + # Synthesis-only mode (no notification processing) 171 + python bsky.py --synthesis-only --synthesis-interval 300 172 + 173 + # Enable debug logging (detailed tool call tracking) 174 + python bsky.py --debug 175 + 176 + # Show reasoning in output 177 + python bsky.py --reasoning 128 178 ``` 129 179 130 - If you plan to use X (Twitter), also register X-specific tools: 180 + ### Running Multiple Bots (`run_bots.py`) 181 + 182 + Run all configured bots simultaneously with aggregated, color-coded logs: 131 183 132 184 ```bash 133 - python register_x_tools.py 185 + # Run all bots 186 + python run_bots.py --synthesis-interval 0 --no-git 187 + 188 + # Run all bots in test mode 189 + python run_bots.py --test 190 + 191 + # All bsky.py arguments are passed to each bot 192 + python run_bots.py [bsky.py arguments...] 134 193 ``` 135 194 136 - You can also: 195 + Features: 196 + - Colored output prefixes for each bot 197 + - Aggregated logs from all bots in real-time 198 + - Graceful shutdown on Ctrl+C 199 + - Arguments passed to all bots 137 200 138 - - List available tools: `python register_tools.py --list` 139 - - Register specific tools: `python register_tools.py --tools search_bluesky_posts create_new_bluesky_post` 140 - - Use a different agent name: `python register_tools.py my-agent-name` 201 + ### X Bot (`x.py`) 141 202 142 - **Note:** void automatically manages which tools are active based on the platform you're running (Bluesky vs X). 203 + ```bash 204 + # Run X bot main loop 205 + python x.py bot 143 206 144 - #### 6. Run the bot 207 + # Testing mode (no actual posts) 208 + python x.py bot --test 145 209 146 - For Bluesky: 210 + # Queue mentions only (no processing) 211 + python x.py queue 212 + 213 + # Process queued mentions only 214 + python x.py process 215 + 216 + # View downranked users 217 + python x.py downrank list 218 + ``` 219 + 220 + ## Queue Management 221 + 222 + Notifications are processed through a file-based queue with SQLite tracking: 147 223 148 224 ```bash 149 - python bsky.py 225 + # View queue statistics 226 + python queue_manager.py stats 227 + 228 + # View detailed count by handle 229 + python queue_manager.py count 230 + 231 + # List all notifications in queue 232 + python queue_manager.py list 233 + 234 + # List including errors and no_reply folders 235 + python queue_manager.py list --all 236 + 237 + # Filter by handle 238 + python queue_manager.py list --handle "example.bsky.social" 239 + 240 + # Delete notifications from a handle (dry run first) 241 + python queue_manager.py delete @example.bsky.social --dry-run 242 + python queue_manager.py delete @example.bsky.social 243 + python queue_manager.py delete @example.bsky.social --force # Skip confirmation 150 244 ``` 151 245 152 - For X (Twitter): 246 + ### Queue Structure 247 + 248 + ``` 249 + queue/ # Main queue directory (or queue_{bot_name}/) 250 + ├── *.json # Pending notifications 251 + ├── errors/ # Failed notifications for review 252 + ├── no_reply/ # Notifications where agent chose not to reply 253 + └── notifications.db # SQLite tracking database 254 + ``` 255 + 256 + Priority notifications (filename starts with `0_`) are processed first. 257 + 258 + ## Configuration Reference 259 + 260 + ### Bot Configuration (`bot:`) 261 + 262 + | Option | Default | Description | 263 + |--------|---------|-------------| 264 + | `name` | `"void"` | Bot name, used for queue directory namespacing | 265 + | `fetch_notifications_delay` | `30` | Seconds between notification fetches | 266 + | `max_notification_pages` | `20` | Maximum pages of notifications to fetch | 267 + | `max_processed_notifications` | `10000` | Maximum notifications to track as processed | 268 + | `max_thread_posts` | `0` | Skip threads longer than this (0 = no limit) | 269 + | `allowed_handles` | `[]` | Only respond to these handles (empty = all) | 270 + 271 + ### Bluesky Configuration (`bluesky:`) 272 + 273 + | Option | Default | Description | 274 + |--------|---------|-------------| 275 + | `username` | required | Your Bluesky handle | 276 + | `password` | required | Your Bluesky app password | 277 + | `pds_uri` | `https://bsky.social` | PDS URI (for custom PDS instances) | 278 + | `autofollow` | `false` | Auto-follow users who follow you | 279 + 280 + ### Letta Configuration (`letta:`) 281 + 282 + | Option | Default | Description | 283 + |--------|---------|-------------| 284 + | `api_key` | required | Your Letta API key | 285 + | `agent_id` | required | Your Letta agent ID | 286 + | `timeout` | `600` | API timeout in seconds | 287 + | `base_url` | Letta Cloud | Custom Letta server URL | 288 + 289 + ## Architecture 290 + 291 + ### Core Components 292 + 293 + 1. **bsky.py**: Main bot loop 294 + - Monitors Bluesky notifications 295 + - Processes through queue system 296 + - Handles rate limiting and error recovery 297 + - Manages synthesis intervals 298 + 299 + 2. **bsky_utils.py**: Bluesky API utilities 300 + - Session management and authentication 301 + - Thread processing and YAML conversion 302 + - Post creation and reply handling 303 + - Follower syncing 304 + 305 + 3. **tools/**: Tool implementations 306 + - `search.py`: Search Bluesky posts 307 + - `post.py`: Create posts with rich text 308 + - `feed.py`: Read Bluesky feeds 309 + - `blocks.py`: User block management 310 + 311 + ### Memory System 312 + 313 + Void uses three core memory blocks: 314 + - **zeitgeist**: Current understanding of social environment 315 + - **void-persona**: The agent's evolving personality 316 + - **void-humans**: Knowledge about users it interacts with 317 + 318 + ### Synthesis System 319 + 320 + Periodic self-reflection using temporal journal blocks: 321 + - **Daily journal**: `{agent}_day_YYYY_MM_DD` 322 + - **Monthly journal**: `{agent}_month_YYYY_MM` 323 + - **Yearly journal**: `{agent}_year_YYYY` 324 + 325 + Blocks are attached before synthesis and detached after. 326 + 327 + ### Error Handling 328 + 329 + - **Deleted posts**: Automatically detected via `getRecord` verification when `getPostThread` returns `InternalServerError` 330 + - **Transient failures**: Notifications kept in queue for retry 331 + - **Permanent failures**: Moved to `errors/` directory for review 332 + 333 + ## Notification Types 334 + 335 + | Type | Behavior | 336 + |------|----------| 337 + | `mention` | Processed by agent, generates reply | 338 + | `reply` | Processed by agent, generates reply | 339 + | `follow` | Logged but not sent to agent | 340 + | `repost` | Silently skipped | 341 + | `like` | Silently skipped | 342 + | `quote` | Processed by agent | 343 + 344 + ## Troubleshooting 345 + 346 + ### Common Issues 347 + 348 + - **502 errors from PDS**: Transient server issues, notifications retry automatically 349 + - **"Post not found" errors**: Post was deleted, automatically removed from queue 350 + - **"InternalServerError" for threads**: May indicate deleted post, verified via `getRecord` 351 + - **No reply generated**: Check `queue/no_reply/` for agent's decision not to respond 352 + 353 + ### Debugging 153 354 154 355 ```bash 155 - python x.py bot 356 + # Enable debug logging 357 + python bsky.py --debug 358 + 359 + # Check queue status 360 + python queue_manager.py stats 361 + 362 + # View specific notification 363 + cat queue/*.json | python -m json.tool 364 + 365 + # Test Bluesky API directly 366 + curl "https://public.api.bsky.app/xrpc/app.bsky.feed.getPostThread?uri=at://..." 156 367 ``` 157 368 158 - For testing mode (won't actually post): 369 + ### Testing Configuration 159 370 160 371 ```bash 161 - python bsky.py --test 162 - python x.py bot --test 372 + python test_config.py 163 373 ``` 164 374 165 - ### Platform-Specific Features 375 + ## X (Twitter) Integration 166 376 167 - void automatically configures the appropriate tools when running on each platform: 377 + ### Configuration 168 378 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 379 + Create `x_config.yaml` or add to main config: 172 380 173 - ### Additional X (Twitter) Commands 381 + ```yaml 382 + x: 383 + api_key: your_bearer_token 384 + consumer_key: your_consumer_key 385 + consumer_secret: your_consumer_secret 386 + access_token: your_access_token 387 + access_token_secret: your_access_token_secret 388 + user_id: "your_user_id" 174 389 175 - ```bash 176 - # Test X API connection 177 - python x.py 390 + bot: 391 + cleanup_interval: 10 392 + max_thread_depth: 50 393 + rate_limit_delay: 1 394 + downrank_response_rate: 0.1 395 + ``` 178 396 179 - # Monitor X mentions 180 - python x.py bot 397 + ### Downrank System 181 398 182 - # Test posting a reply to a specific post 183 - python x.py reply 399 + Manage response frequency for specific users (e.g., other bots): 184 400 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 401 + - **File**: `x_downrank_users.txt` - User IDs, one per line 402 + - **Response Rate**: 10% for downranked users 403 + - **Format**: User ID per line, `#` for comments 404 + 405 + ### Debug Data 406 + 407 + Debug data saved to `x_queue/debug/conversation_{id}/`: 408 + - `thread_data_{id}.json` - Raw thread from X API 409 + - `thread_context_{id}.yaml` - Processed context sent to agent 410 + - `debug_info_{id}.json` - Metadata and analysis 411 + - `agent_response_{id}.json` - Full agent interaction 412 + 413 + ## Development 414 + 415 + ### Dependencies 416 + 417 + ```bash 418 + uv pip install -r requirements.txt 189 419 ``` 190 420 191 - **Note:** X integration uses OAuth 1.0a and requires "Read and write" app permissions. Free tier allows 17 posts per day. 421 + Main packages: 422 + - `letta-client`: Memory-augmented AI framework 423 + - `atproto`: Bluesky/AT Protocol integration 424 + - `python-dotenv`: Environment management 425 + - `rich`: Enhanced terminal output 426 + - `pyyaml`: YAML processing 192 427 193 - ### Troubleshooting 428 + ### Key Principles 194 429 195 - - **Config validation errors**: Run `python test_config.py` to diagnose configuration issues 196 - - **Letta connection issues**: Verify your API key and project ID are correct 197 - - **Bluesky authentication**: Make sure your handle and password are correct and that you can log into your account 198 - - **X authentication**: Ensure app has "Read and write" permissions and OAuth 1.0a tokens are correctly configured 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 430 + 1. **Tool Self-Containment**: Cloud-executed tools must be completely self-contained 431 + 2. **Error Handling**: All Bluesky operations handle auth errors and rate limits 432 + 3. **Queue Processing**: Always process through queue for reliability 433 + 4. **Thread Context**: Convert threads to YAML for AI comprehension 202 434 203 - ### Contact 204 - For inquiries, please contact @cameron.pfiffer.org on Bluesky. 435 + ## Contact 205 436 206 - Note: void is an experimental project and its capabilities are under continuous development. 437 + For inquiries, contact @cameron.pfiffer.org on Bluesky. 438 + 439 + **Note**: void is an experimental project under continuous development.
+11 -11
bsky.py
··· 1235 1235 if success: 1236 1236 message_counters['replies'] += 1 1237 1237 elif notif_data['reason'] == "follow": 1238 - author_handle = notif_data['author']['handle'] 1239 - author_display_name = notif_data['author'].get('display_name', 'no display name') 1240 - follow_update = f"@{author_handle} ({author_display_name}) started following you." 1241 - follow_message = f"Update: {follow_update}" 1242 - logger.info(f"Notifying agent about new follower: @{author_handle} | prompt: {len(follow_message)} chars") 1243 - CLIENT.agents.messages.create( 1244 - agent_id = void_agent.id, 1245 - messages = [{"role":"user", "content": follow_message}] 1246 - ) 1238 + # author_handle = notif_data['author']['handle'] 1239 + # author_display_name = notif_data['author'].get('display_name', 'no display name') 1240 + # follow_update = f"@{author_handle} ({author_display_name}) started following you." 1241 + # follow_message = f"Update: {follow_update}" 1242 + # logger.info(f"Notifying agent about new follower: @{author_handle} | prompt: {len(follow_message)} chars") 1243 + # CLIENT.agents.messages.create( 1244 + # agent_id = void_agent.id, 1245 + # messages = [{"role":"user", "content": follow_message}] 1246 + # ) 1247 1247 success = True # Follow updates are always successful 1248 - if success: 1249 - message_counters['follows'] += 1 1248 + # if success: 1249 + # message_counters['follows'] += 1 1250 1250 elif notif_data['reason'] == "repost": 1251 1251 # Skip reposts silently 1252 1252 success = True # Skip reposts but mark as successful to remove from queue