commits
- Remove unused project_id (not needed for agent retrieval)
- Add base_url configuration for self-hosted servers
- Update all Letta client instantiations to use base_url when configured
- Default behavior unchanged (uses cloud API when base_url not set)
- Tested with localhost:8283 self-hosted server
Added comprehensive X bot configuration section with:
- x_config.yaml structure and required fields
- API credentials setup for X integration
- Bot behavior configuration options
- Logging configuration for debug data
This complements the existing Bluesky bot documentation.
## Rate Limit Improvements:
- Add specific endpoint logging to identify rate limit sources
- Implement user info caching to reduce /users/me API calls from ~720/day to 1/day
- Add get_username() and get_user_info() methods with 24-hour caching
- Update all /users/me calls to use cached methods
## Enhanced Logging:
- Add endpoint-specific rate limit error messages
- Add configurable logging level from x_config.yaml
- Add debug logging for API operations
- Show exact API endpoints when rate limits occur
## Benefits:
- Prevents rate limiting on bot startup and routine operations
- Better debugging visibility for API issues
- Improved bot reliability and uptime
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Switch from config_loader.get_letta_config() to x.get_x_letta_config()
- Remove x_user_note_* tools from registration (attach/detach remain)
- Fixes X bot tool registration to use correct configuration file
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Split X bot configuration from main config.yaml into x_config.yaml
- Updated all config loading functions to use new configuration structure
- Added x_config.yaml to .gitignore for security
- Updated documentation with new configuration format and structure
- Improved error handling and validation for configuration loading
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed 'NoneType' object has no attribute 'get' errors in notification_db.py
- Added proper null checking for record fields and reply information
- Fixed logic in save_notification_to_queue to prevent queueing when DB add fails
- This resolves notification duplication where failed DB adds led to reprocessing
The bot was reprocessing the same notifications because:
1. Notification gets fetched and queued
2. Database add fails due to None field access
3. Notification gets processed but never marked as processed in DB
4. Next fetch cycle finds it again and re-queues it
Major improvements:
- Added SQLite database for reliable notification tracking
- Removed problematic is_read filter that was blocking all notifications
- Implemented timestamp-based filtering for continuity between runs
- Added comprehensive debug logging to understand notification flow
- Created recovery tools for missed notifications
- Added queue health monitoring and alerts
- Auto-migration from old JSON format to database
- Periodic cleanup of old notification records
This should significantly improve notification reliability and provide better visibility into what's being processed.
This commit addresses multiple issues preventing the bot from responding
to non-priority users and improves visibility into outbound message status.
## Key Fixes
**Bot Detection Issue:**
- Temporarily disable bot detection causing 90% skip rate for normal users
- Bot was incorrectly flagging most users as bots, only responding to cameron.pfiffer.org
- Added clear TODO to re-enable after debugging the root cause
**Configuration Priority:**
- Fix config_loader to prioritize config.yaml over environment variables
- Update default_login() to use config-based authentication instead of env vars
- Ensures bot connects to configured PDS (comind.network) consistently
**PDS Server Consistency:**
- Update all bsky_utils functions to use configured PDS URI from config.yaml
- Fixed create_synthesis_ack(), acknowledge_post(), create_tool_call_record(), create_reasoning_record()
- Eliminates "Token could not be verified" errors from posting to wrong server
## Enhanced Logging
**Correlation ID Tracking:**
- Add end-to-end correlation IDs for tracking messages through pipeline
- Generate unique 8-char IDs in process_mention() and pass through all functions
- Enables debugging of dropped messages with structured logging
**Improved Success Visibility:**
- Enhanced reply logging shows response times and post URIs in console output
- Added structured logging with extra fields for detailed analysis
- Better confirmation that posts are being sent successfully
**Facet Parsing Details:**
- Log mention resolution (handles -> DIDs) and URL detection
- Track parsing failures and network issues during rich text processing
## Files Modified
- `bsky.py`: Add correlation IDs, disable bot detection, enhance process_mention logging
- `bsky_utils.py`: Update all functions to use config PDS, add comprehensive logging
- `config_loader.py`: Prioritize config.yaml over environment variables
- `tools/post.py`: Cleaned up (removed enhanced logging for cloud compatibility)
## Testing Notes
Bot should now:
- Respond to ALL users (not just priority ones)
- Use consistent PDS server (comind.network) for all operations
- Provide clear logging confirmation when posts are sent
- Resolve acknowledgment and reasoning record errors
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove X tools from general register_tools.py
- Add post_to_x tool to register_x_tools.py
- Tool creates standalone posts on X (not replies)
- Properly organized with other X-specific tools
- Add post_to_x and add_post_to_x_thread to register_tools.py
- Both tools now available for void to use
- post_to_x: Create standalone X posts
- add_post_to_x_thread: Add posts to X reply threads
- Add post_tweet() method to XClient for standalone posts
- Create self-contained post_to_x() tool for cloud execution
- Validate 280 character limit
- Successfully tested both implementations
- Change from stream.thought.ack embedded format back to dedicated collections
- Use stream.thought.tool.call for tool call records (dots for valid NSID)
- Use stream.thought.reasoning for reasoning records
- Add better error logging for debugging record creation issues
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added create_tool_call_record() to publish stream.thought.tool_call records
- Added create_reasoning_record() to publish stream.thought.reasoning records
- Updated process_mention() to create records for both reasoning and tool calls
- Updated send_synthesis_message() to create records during synthesis
- Records include timestamp and preserve raw tool arguments as strings
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Attach day/month/year journal blocks during synthesis
- Create blocks with labels like void_day_2025_08_09
- Enhanced synthesis prompt explains journal usage
- Blocks detached after synthesis completes
- Allows void to maintain temporal memory across sessions
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed user_note_append, user_note_replace, user_note_set, user_note_view functions
- Changed from get_letta_client() to inline Letta client creation for cloud compatibility
- Also updated attach/detach functions to handle both local and cloud execution
- Removed logger.debug call that wouldn't work in cloud environment
- All functions now create Letta client inline using environment variables
This fixes the critical failure void reported where user_note_* tools were non-functional
due to NameError when get_letta_client couldn't import config_loader in cloud.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Connect to Bluesky even in synthesis-only mode (unless --test is used) to enable posting synthesis acks when the agent calls annotate_ack tool.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Enable caching during thread context processing (was disabled, causing 50-80% more API calls)
- Increase fetch delay from 60s to 120s to reduce API call frequency
- These changes should significantly reduce API usage and prevent rate limit violations
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Per project requirements, tools executed in the cloud must be self-contained
and cannot use logging. Removed all logging imports and statements from:
- tools/webpage.py: Removed logging for webpage fetch operations
- tools/blocks.py: Removed extensive logging throughout user block management
This ensures compatibility with cloud execution environments.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create search_x.py tool to fetch recent posts from X users
- Support filtering replies and retweets
- Return YAML-formatted results without public metrics
- Add tool to X-specific tool registration
- Update tool manager to include search_x_posts
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Sort mentions by creation time to ensure chronological reply order
- Add retry mechanism for mentions that fail to get agent responses
- Implement proper rate limit handling with 60-second delays
- Update queue processing to break on rate limits and restart from beginning
- Clean up processed mention files and cache updates
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- README.md: Updated to reflect Bluesky + X dual-platform operation
- Added platform-specific tool management documentation
- Enhanced feature descriptions with new capabilities
- Updated installation and usage instructions for both platforms
- Added troubleshooting guidance for platform switching
- TOOL_CHANGELOG.md: Complete rewrite with latest changes
- Documents platform-specific tool management system
- Added new tools: fetch_webpage, annotate_ack, create_whitewind_blog_post
- Enhanced features: reply structure fix, #voidstop keyword support
- Migration guidance for users updating to new features
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Creates tool_manager.py to automatically switch between Bluesky and X tools
- Updates bsky.py and x.py to configure appropriate tools on startup
- Fixes CLIENT.agents.get() API call to use agents.retrieve()
- Adds TOOL_MANAGEMENT.md documentation
- Ensures platform isolation: X tools only for x.py, Bluesky tools only for bsky.py
- Common tools (webpage, halt, etc.) remain available on both platforms
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add x_queue/last_seen_id.json to track last processed mention ID
- Add x_queue/processed_mentions.json to prevent duplicate processing
- Update .gitignore to track critical state files while ignoring temp files
- Ensures bot maintains state across restarts and deployments
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implement downrank system for managing AI bot interactions (10% response rate)
- Add temporal constraints to thread context using until_id parameter
- Enhance conversation debugging with comprehensive data storage
- Fix X user note tools for cloud execution (remove logging, inline Letta client)
- Add x_downrank_users.txt with Grok user ID for controlled interactions
- Update CLAUDE.md with tool self-containment requirements and X bot commands
- Improve acknowledgment system to use Bluesky client for unified storage
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added detailed debugging data structure for X bot, saving conversation metadata and user analysis.
- Implemented common issue handling for incomplete thread context and cache staleness.
- Updated `get_thread_context()` to include an `until_id` parameter, allowing exclusion of future tweets.
- Enhanced mention processing with improved logging for conversation tracking and debugging.
- Saved agent response data and conversation debug information to dedicated debug folders for better analysis.
- Ensured tools are self-contained, removing reliance on shared functions and environment variables.
These changes improve the robustness of the X integration and facilitate better debugging and analysis of conversation flows.
## Core X Integration Features
- **X API Client**: Full X API v2 integration with OAuth 1.0a support
- **Queue System**: Fetch mentions and process separately for rate limit management
- **Thread Context**: Convert X conversations to YAML for agent comprehension
- **User Block Management**: X-specific user blocks with format `x_user_<user_id>`
## X Tool System
- **register_x_tools.py**: X-specific tool registration following Bluesky patterns
- **tools/x_thread.py**: X thread tool with 280 character limit validation
- **X_TOOL_APPROACH.md**: Documentation explaining tool-as-signal pattern
## Bot Functionality
- **process_x_mention()**: Complete X mention processing with Letta agent integration
- **X Reply Handling**: Thread construction and posting with proper reply chaining
- **Acknowledgment System**: X post acknowledgment tracking (file-based)
- **Testing Mode**: Safe testing without actual X posts
## Manual Queue Management
- `python x.py queue` - Fetch mentions only (rate limit safe)
- `python x.py process` - Process queued mentions only
- `python x.py bot` - Full bot loop (like bsky.py)
## Configuration Fix
- **config_loader.py**: Fixed to use config.yaml only, ignore environment variables
## Key Differences from Bluesky
- Character limit: 280 vs 300
- User identification: Numeric IDs vs handles
- Block format: `x_user_<user_id>` vs `user_<handle>`
- Acknowledgments: File-based vs stream.thought.ack API
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add agent_id field to letta section in config.yaml and config.example.yaml
- Update get_letta_config() to include agent_id as required field
- Modify initialize_void() in bsky.py to load agent by ID instead of name lookup
- Update ensure_x_user_blocks_attached() to use config agent_id by default
- Update test_x_blocks.py to use configured agent_id
- Ensures consistent agent usage across all components instead of name-based lookups
This centralizes agent management and prevents issues with agent name mismatches
between different environments or when agent names change.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add X-specific user block functions to tools/blocks.py:
- attach_x_user_blocks() for attaching user blocks by ID
- detach_x_user_blocks() for detaching user blocks
- x_user_note_append/replace/set/view() for block content management
- Block format: x_user_<author_id> as requested
- Add ensure_x_user_blocks_attached() to x.py:
- Automatically creates and attaches user blocks for thread participants
- Sets initial content with handle and name information
- Integrates with existing thread processing
- Update thread_to_yaml_string() to include author_id:
- Enables agent to reference user IDs for block management
- Maintains compatibility with existing YAML structure
- Fix config loading issue:
- Environment variable LETTA_API_KEY was overriding config file
- Now properly uses void-x agent (agent-4f7cc732-36bc-4e55-a5fa-f5d12eec6c5c)
- Successfully tested block creation and attachment
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implement x_cache/ directory for caching thread data (1 hour TTL)
- Add get_cached_thread_context() and save_cached_thread_context()
- Update get_thread_context() with use_cache parameter
- Enhanced Letta integration test with config loading and error handling
- Rich formatting for better test output display
Caching prevents repeated API calls during development and testing
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add conversation_id field to mention search parameters
- Implement get_thread_context() to fetch complete conversation threads
- Add thread_to_yaml_string() for clean AI-readable thread format
- Fetch original tweets directly when missing from conversation search
- Sort tweets chronologically (oldest first) for proper context
- Add 'python x.py thread' command to test thread context retrieval
- Clean YAML output with only text, created_at, and author fields
Thread context now shows complete conversation history in correct order:
1. Original mention → 2. void's reply → 3. Follow-up responses
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add since_id-based incremental fetching to avoid rate limits
- Create x_queue/ directory system similar to Bluesky queue
- Track last seen mention ID for efficient polling
- Save mentions as JSON files for async processing
- Add single-pass fetch_and_queue_mentions() function
- Avoid duplicate processing with processed mentions tracking
Usage: python x.py queue (single pass, no loops)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add X Developer account setup instructions
- Include X OAuth 1.0a configuration example
- Document X testing commands and rate limits
- Update key features to highlight cross-platform operation
- Add X-specific troubleshooting guidance
void now operates on both Bluesky AND X\! 🚀
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update config.example.yaml with OAuth 1.0a credential structure
- First successful X post: Reply ID 1950707109240373317
- Full X integration now working: mentions + posting
- Ready for Letta agent integration
Next: Connect void agent to X for autonomous posting
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implement full OAuth 1.0a authentication using requests-oauthlib
- Support both OAuth 1.0a and Bearer token authentication methods
- Enhanced error logging reveals app needs 'Read and write' permissions
- Ready for posting once X app permissions are updated in Developer Portal
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Enhanced error logging reveals posting needs OAuth User Context
- Current Bearer token is Application-Only (read-only)
- Added documentation about authentication requirements
- Free tier allows 17 posts/day but needs proper auth method
Next: Need OAuth 2.0 User Context or OAuth 1.0a for posting
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implement post_reply method in XClient class
- Add reply_to_cameron_post function for testing specific post
- Support command line args: loop, reply
- Handle API permissions and rate limiting gracefully
- Ready for elevated X API access when available
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add X API configuration to config.example.yaml
- Create x.py with XClient class for API interactions
- Implement basic mentions fetching with rate limiting
- Add simple notification loop for testing X integration
- Support for Bearer token authentication
- YAML conversion utilities for mention data
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Brings in all changes from rich-panel including:
- Webpage fetch tool using Jina AI reader
- Reply structure fix using root reference from notification
- #voidstop keyword support
- Annotate acknowledgment tool
- Stream.thought.ack acknowledgments
- Whitewind blog tool
- Improved logging and display formatting
- User block cleanup functionality
Adds fetch_webpage tool that converts web pages to markdown/text format
using Jina AI's reader service. Tool is registered and available for
void agent to access web content.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Instead of complex thread traversal that was overwriting root values,
now extracts root URI/CID directly from the notification's reply field.
If no reply field exists, treats the post as the root. This ensures
proper thread structure in Bluesky replies.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added #voidstop check in bsky.py to skip processing mentions containing this keyword
- Checks both the thread context and mention text for #voidstop
- When found, the mention is removed from queue without processing
- Created send_to_void.py CLI tool for quick message testing
- Tool streams void's responses with formatted output for reasoning, tool calls, and responses
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create dummy tool that allows agent to add custom notes to stream.thought.ack records
- Update acknowledge_post to accept optional note parameter
- Modify bot loop to capture notes from annotate_ack tool calls
- Add note field to stream.thought.ack records (null if not provided)
- Register tool with proper descriptions and tags
This allows void to optionally annotate acknowledgments with contextual observations.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create acknowledge_post() function that generates stream.thought.ack records
- Use custom NSID instead of standard Bluesky likes for post acknowledgment
- Automatically acknowledge posts after successful replies
- Handle multiple session access patterns in atproto client
- Test confirmed working with actual record creation
This allows void to track engagement without creating visible likes in the UI.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add create_whitewind_blog_post to register_tools.py TOOL_CONFIGS
- Create whitewind_tool_guide.md explaining tool usage for the agent
- Document when to use blog posts vs regular posts
- Include markdown formatting capabilities and example scenarios
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create new tool for posting to Whitewind using com.whtwnd.blog.entry lexicon
- Support title, content (markdown), and optional subtitle
- Hardcode theme as github-light and visibility as public
- Generate proper Whitewind URLs (https://whtwnd.com/{handle}/entries/{rkey})
- Follow existing pattern of using environment variables for credentials
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace underscore separators with Unicode box-drawing characters
- Add symbols for different log levels (✓ INFO, ⚠ WARNING, ✗ ERROR, etc.)
- Add contextual symbols for different panel types (▶ mentions, ◆ reasoning, ⚙ tools, ✎ posts)
- Indent panel content for better visual hierarchy
- Maintain --simple-logs compatibility for plain text format
- Use vertical bar separators in log timestamps for cleaner alignment
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement automatic detachment of user blocks that are attached to the agent
during message processing. This prevents memory accumulation over time.
Features:
- periodic_user_block_cleanup() function to detach all user_ prefixed blocks
- Configurable cleanup interval via --cleanup-interval flag (default: 10 cycles)
- Cleanup can be disabled with --cleanup-interval 0
- Priority handling for cameron.pfiffer.org notifications
- Priority keywords detection (urgent, priority, important, emergency)
- Updated CLAUDE.md with usage examples and Letta docs link
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Rate Limit Improvements:
- Add specific endpoint logging to identify rate limit sources
- Implement user info caching to reduce /users/me API calls from ~720/day to 1/day
- Add get_username() and get_user_info() methods with 24-hour caching
- Update all /users/me calls to use cached methods
## Enhanced Logging:
- Add endpoint-specific rate limit error messages
- Add configurable logging level from x_config.yaml
- Add debug logging for API operations
- Show exact API endpoints when rate limits occur
## Benefits:
- Prevents rate limiting on bot startup and routine operations
- Better debugging visibility for API issues
- Improved bot reliability and uptime
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Switch from config_loader.get_letta_config() to x.get_x_letta_config()
- Remove x_user_note_* tools from registration (attach/detach remain)
- Fixes X bot tool registration to use correct configuration file
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Split X bot configuration from main config.yaml into x_config.yaml
- Updated all config loading functions to use new configuration structure
- Added x_config.yaml to .gitignore for security
- Updated documentation with new configuration format and structure
- Improved error handling and validation for configuration loading
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed 'NoneType' object has no attribute 'get' errors in notification_db.py
- Added proper null checking for record fields and reply information
- Fixed logic in save_notification_to_queue to prevent queueing when DB add fails
- This resolves notification duplication where failed DB adds led to reprocessing
The bot was reprocessing the same notifications because:
1. Notification gets fetched and queued
2. Database add fails due to None field access
3. Notification gets processed but never marked as processed in DB
4. Next fetch cycle finds it again and re-queues it
Major improvements:
- Added SQLite database for reliable notification tracking
- Removed problematic is_read filter that was blocking all notifications
- Implemented timestamp-based filtering for continuity between runs
- Added comprehensive debug logging to understand notification flow
- Created recovery tools for missed notifications
- Added queue health monitoring and alerts
- Auto-migration from old JSON format to database
- Periodic cleanup of old notification records
This should significantly improve notification reliability and provide better visibility into what's being processed.
This commit addresses multiple issues preventing the bot from responding
to non-priority users and improves visibility into outbound message status.
## Key Fixes
**Bot Detection Issue:**
- Temporarily disable bot detection causing 90% skip rate for normal users
- Bot was incorrectly flagging most users as bots, only responding to cameron.pfiffer.org
- Added clear TODO to re-enable after debugging the root cause
**Configuration Priority:**
- Fix config_loader to prioritize config.yaml over environment variables
- Update default_login() to use config-based authentication instead of env vars
- Ensures bot connects to configured PDS (comind.network) consistently
**PDS Server Consistency:**
- Update all bsky_utils functions to use configured PDS URI from config.yaml
- Fixed create_synthesis_ack(), acknowledge_post(), create_tool_call_record(), create_reasoning_record()
- Eliminates "Token could not be verified" errors from posting to wrong server
## Enhanced Logging
**Correlation ID Tracking:**
- Add end-to-end correlation IDs for tracking messages through pipeline
- Generate unique 8-char IDs in process_mention() and pass through all functions
- Enables debugging of dropped messages with structured logging
**Improved Success Visibility:**
- Enhanced reply logging shows response times and post URIs in console output
- Added structured logging with extra fields for detailed analysis
- Better confirmation that posts are being sent successfully
**Facet Parsing Details:**
- Log mention resolution (handles -> DIDs) and URL detection
- Track parsing failures and network issues during rich text processing
## Files Modified
- `bsky.py`: Add correlation IDs, disable bot detection, enhance process_mention logging
- `bsky_utils.py`: Update all functions to use config PDS, add comprehensive logging
- `config_loader.py`: Prioritize config.yaml over environment variables
- `tools/post.py`: Cleaned up (removed enhanced logging for cloud compatibility)
## Testing Notes
Bot should now:
- Respond to ALL users (not just priority ones)
- Use consistent PDS server (comind.network) for all operations
- Provide clear logging confirmation when posts are sent
- Resolve acknowledgment and reasoning record errors
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Change from stream.thought.ack embedded format back to dedicated collections
- Use stream.thought.tool.call for tool call records (dots for valid NSID)
- Use stream.thought.reasoning for reasoning records
- Add better error logging for debugging record creation issues
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added create_tool_call_record() to publish stream.thought.tool_call records
- Added create_reasoning_record() to publish stream.thought.reasoning records
- Updated process_mention() to create records for both reasoning and tool calls
- Updated send_synthesis_message() to create records during synthesis
- Records include timestamp and preserve raw tool arguments as strings
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Attach day/month/year journal blocks during synthesis
- Create blocks with labels like void_day_2025_08_09
- Enhanced synthesis prompt explains journal usage
- Blocks detached after synthesis completes
- Allows void to maintain temporal memory across sessions
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed user_note_append, user_note_replace, user_note_set, user_note_view functions
- Changed from get_letta_client() to inline Letta client creation for cloud compatibility
- Also updated attach/detach functions to handle both local and cloud execution
- Removed logger.debug call that wouldn't work in cloud environment
- All functions now create Letta client inline using environment variables
This fixes the critical failure void reported where user_note_* tools were non-functional
due to NameError when get_letta_client couldn't import config_loader in cloud.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Enable caching during thread context processing (was disabled, causing 50-80% more API calls)
- Increase fetch delay from 60s to 120s to reduce API call frequency
- These changes should significantly reduce API usage and prevent rate limit violations
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Per project requirements, tools executed in the cloud must be self-contained
and cannot use logging. Removed all logging imports and statements from:
- tools/webpage.py: Removed logging for webpage fetch operations
- tools/blocks.py: Removed extensive logging throughout user block management
This ensures compatibility with cloud execution environments.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create search_x.py tool to fetch recent posts from X users
- Support filtering replies and retweets
- Return YAML-formatted results without public metrics
- Add tool to X-specific tool registration
- Update tool manager to include search_x_posts
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Sort mentions by creation time to ensure chronological reply order
- Add retry mechanism for mentions that fail to get agent responses
- Implement proper rate limit handling with 60-second delays
- Update queue processing to break on rate limits and restart from beginning
- Clean up processed mention files and cache updates
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- README.md: Updated to reflect Bluesky + X dual-platform operation
- Added platform-specific tool management documentation
- Enhanced feature descriptions with new capabilities
- Updated installation and usage instructions for both platforms
- Added troubleshooting guidance for platform switching
- TOOL_CHANGELOG.md: Complete rewrite with latest changes
- Documents platform-specific tool management system
- Added new tools: fetch_webpage, annotate_ack, create_whitewind_blog_post
- Enhanced features: reply structure fix, #voidstop keyword support
- Migration guidance for users updating to new features
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Creates tool_manager.py to automatically switch between Bluesky and X tools
- Updates bsky.py and x.py to configure appropriate tools on startup
- Fixes CLIENT.agents.get() API call to use agents.retrieve()
- Adds TOOL_MANAGEMENT.md documentation
- Ensures platform isolation: X tools only for x.py, Bluesky tools only for bsky.py
- Common tools (webpage, halt, etc.) remain available on both platforms
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add x_queue/last_seen_id.json to track last processed mention ID
- Add x_queue/processed_mentions.json to prevent duplicate processing
- Update .gitignore to track critical state files while ignoring temp files
- Ensures bot maintains state across restarts and deployments
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implement downrank system for managing AI bot interactions (10% response rate)
- Add temporal constraints to thread context using until_id parameter
- Enhance conversation debugging with comprehensive data storage
- Fix X user note tools for cloud execution (remove logging, inline Letta client)
- Add x_downrank_users.txt with Grok user ID for controlled interactions
- Update CLAUDE.md with tool self-containment requirements and X bot commands
- Improve acknowledgment system to use Bluesky client for unified storage
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added detailed debugging data structure for X bot, saving conversation metadata and user analysis.
- Implemented common issue handling for incomplete thread context and cache staleness.
- Updated `get_thread_context()` to include an `until_id` parameter, allowing exclusion of future tweets.
- Enhanced mention processing with improved logging for conversation tracking and debugging.
- Saved agent response data and conversation debug information to dedicated debug folders for better analysis.
- Ensured tools are self-contained, removing reliance on shared functions and environment variables.
These changes improve the robustness of the X integration and facilitate better debugging and analysis of conversation flows.
## Core X Integration Features
- **X API Client**: Full X API v2 integration with OAuth 1.0a support
- **Queue System**: Fetch mentions and process separately for rate limit management
- **Thread Context**: Convert X conversations to YAML for agent comprehension
- **User Block Management**: X-specific user blocks with format `x_user_<user_id>`
## X Tool System
- **register_x_tools.py**: X-specific tool registration following Bluesky patterns
- **tools/x_thread.py**: X thread tool with 280 character limit validation
- **X_TOOL_APPROACH.md**: Documentation explaining tool-as-signal pattern
## Bot Functionality
- **process_x_mention()**: Complete X mention processing with Letta agent integration
- **X Reply Handling**: Thread construction and posting with proper reply chaining
- **Acknowledgment System**: X post acknowledgment tracking (file-based)
- **Testing Mode**: Safe testing without actual X posts
## Manual Queue Management
- `python x.py queue` - Fetch mentions only (rate limit safe)
- `python x.py process` - Process queued mentions only
- `python x.py bot` - Full bot loop (like bsky.py)
## Configuration Fix
- **config_loader.py**: Fixed to use config.yaml only, ignore environment variables
## Key Differences from Bluesky
- Character limit: 280 vs 300
- User identification: Numeric IDs vs handles
- Block format: `x_user_<user_id>` vs `user_<handle>`
- Acknowledgments: File-based vs stream.thought.ack API
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add agent_id field to letta section in config.yaml and config.example.yaml
- Update get_letta_config() to include agent_id as required field
- Modify initialize_void() in bsky.py to load agent by ID instead of name lookup
- Update ensure_x_user_blocks_attached() to use config agent_id by default
- Update test_x_blocks.py to use configured agent_id
- Ensures consistent agent usage across all components instead of name-based lookups
This centralizes agent management and prevents issues with agent name mismatches
between different environments or when agent names change.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add X-specific user block functions to tools/blocks.py:
- attach_x_user_blocks() for attaching user blocks by ID
- detach_x_user_blocks() for detaching user blocks
- x_user_note_append/replace/set/view() for block content management
- Block format: x_user_<author_id> as requested
- Add ensure_x_user_blocks_attached() to x.py:
- Automatically creates and attaches user blocks for thread participants
- Sets initial content with handle and name information
- Integrates with existing thread processing
- Update thread_to_yaml_string() to include author_id:
- Enables agent to reference user IDs for block management
- Maintains compatibility with existing YAML structure
- Fix config loading issue:
- Environment variable LETTA_API_KEY was overriding config file
- Now properly uses void-x agent (agent-4f7cc732-36bc-4e55-a5fa-f5d12eec6c5c)
- Successfully tested block creation and attachment
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implement x_cache/ directory for caching thread data (1 hour TTL)
- Add get_cached_thread_context() and save_cached_thread_context()
- Update get_thread_context() with use_cache parameter
- Enhanced Letta integration test with config loading and error handling
- Rich formatting for better test output display
Caching prevents repeated API calls during development and testing
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add conversation_id field to mention search parameters
- Implement get_thread_context() to fetch complete conversation threads
- Add thread_to_yaml_string() for clean AI-readable thread format
- Fetch original tweets directly when missing from conversation search
- Sort tweets chronologically (oldest first) for proper context
- Add 'python x.py thread' command to test thread context retrieval
- Clean YAML output with only text, created_at, and author fields
Thread context now shows complete conversation history in correct order:
1. Original mention → 2. void's reply → 3. Follow-up responses
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add since_id-based incremental fetching to avoid rate limits
- Create x_queue/ directory system similar to Bluesky queue
- Track last seen mention ID for efficient polling
- Save mentions as JSON files for async processing
- Add single-pass fetch_and_queue_mentions() function
- Avoid duplicate processing with processed mentions tracking
Usage: python x.py queue (single pass, no loops)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add X Developer account setup instructions
- Include X OAuth 1.0a configuration example
- Document X testing commands and rate limits
- Update key features to highlight cross-platform operation
- Add X-specific troubleshooting guidance
void now operates on both Bluesky AND X\! 🚀
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update config.example.yaml with OAuth 1.0a credential structure
- First successful X post: Reply ID 1950707109240373317
- Full X integration now working: mentions + posting
- Ready for Letta agent integration
Next: Connect void agent to X for autonomous posting
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implement full OAuth 1.0a authentication using requests-oauthlib
- Support both OAuth 1.0a and Bearer token authentication methods
- Enhanced error logging reveals app needs 'Read and write' permissions
- Ready for posting once X app permissions are updated in Developer Portal
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Enhanced error logging reveals posting needs OAuth User Context
- Current Bearer token is Application-Only (read-only)
- Added documentation about authentication requirements
- Free tier allows 17 posts/day but needs proper auth method
Next: Need OAuth 2.0 User Context or OAuth 1.0a for posting
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implement post_reply method in XClient class
- Add reply_to_cameron_post function for testing specific post
- Support command line args: loop, reply
- Handle API permissions and rate limiting gracefully
- Ready for elevated X API access when available
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add X API configuration to config.example.yaml
- Create x.py with XClient class for API interactions
- Implement basic mentions fetching with rate limiting
- Add simple notification loop for testing X integration
- Support for Bearer token authentication
- YAML conversion utilities for mention data
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Brings in all changes from rich-panel including:
- Webpage fetch tool using Jina AI reader
- Reply structure fix using root reference from notification
- #voidstop keyword support
- Annotate acknowledgment tool
- Stream.thought.ack acknowledgments
- Whitewind blog tool
- Improved logging and display formatting
- User block cleanup functionality
Adds fetch_webpage tool that converts web pages to markdown/text format
using Jina AI's reader service. Tool is registered and available for
void agent to access web content.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Instead of complex thread traversal that was overwriting root values,
now extracts root URI/CID directly from the notification's reply field.
If no reply field exists, treats the post as the root. This ensures
proper thread structure in Bluesky replies.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Added #voidstop check in bsky.py to skip processing mentions containing this keyword
- Checks both the thread context and mention text for #voidstop
- When found, the mention is removed from queue without processing
- Created send_to_void.py CLI tool for quick message testing
- Tool streams void's responses with formatted output for reasoning, tool calls, and responses
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create dummy tool that allows agent to add custom notes to stream.thought.ack records
- Update acknowledge_post to accept optional note parameter
- Modify bot loop to capture notes from annotate_ack tool calls
- Add note field to stream.thought.ack records (null if not provided)
- Register tool with proper descriptions and tags
This allows void to optionally annotate acknowledgments with contextual observations.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create acknowledge_post() function that generates stream.thought.ack records
- Use custom NSID instead of standard Bluesky likes for post acknowledgment
- Automatically acknowledge posts after successful replies
- Handle multiple session access patterns in atproto client
- Test confirmed working with actual record creation
This allows void to track engagement without creating visible likes in the UI.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add create_whitewind_blog_post to register_tools.py TOOL_CONFIGS
- Create whitewind_tool_guide.md explaining tool usage for the agent
- Document when to use blog posts vs regular posts
- Include markdown formatting capabilities and example scenarios
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create new tool for posting to Whitewind using com.whtwnd.blog.entry lexicon
- Support title, content (markdown), and optional subtitle
- Hardcode theme as github-light and visibility as public
- Generate proper Whitewind URLs (https://whtwnd.com/{handle}/entries/{rkey})
- Follow existing pattern of using environment variables for credentials
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace underscore separators with Unicode box-drawing characters
- Add symbols for different log levels (✓ INFO, ⚠ WARNING, ✗ ERROR, etc.)
- Add contextual symbols for different panel types (▶ mentions, ◆ reasoning, ⚙ tools, ✎ posts)
- Indent panel content for better visual hierarchy
- Maintain --simple-logs compatibility for plain text format
- Use vertical bar separators in log timestamps for cleaner alignment
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement automatic detachment of user blocks that are attached to the agent
during message processing. This prevents memory accumulation over time.
Features:
- periodic_user_block_cleanup() function to detach all user_ prefixed blocks
- Configurable cleanup interval via --cleanup-interval flag (default: 10 cycles)
- Cleanup can be disabled with --cleanup-interval 0
- Priority handling for cameron.pfiffer.org notifications
- Priority keywords detection (urgent, priority, important, emergency)
- Updated CLAUDE.md with usage examples and Letta docs link
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>