commits
- 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>
- 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>
Replace Rich panel formatting with simple text output using underscores
for titles. This provides a cleaner, more minimal logging style without
external dependencies.
Changes:
- Remove all Rich imports (Panel, Console, Table, Text)
- Replace panel displays with title + underscores format
- Remove --rich command line option
- Update log_with_panel to use simple print statements
- Remove USE_RICH and console global variables
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Display archival memory insert content in Rich panel with preview
- Show success/error messages for archival memory insert results
- Consistent formatting with other tool calls
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace plain text reply thread with Rich panels for better formatting
- Hide verbose log messages by changing to debug level
- Filter out usage_statistics and stop_reason message types
- Clean up tool result displays for bluesky posts
- Skip archival_memory_insert result displays (always None)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Rich panel formatting for all logs when --rich flag is used
- Add --reasoning flag to control reasoning display and log level
- Add --simple-logs flag for cleaner log format without timestamps
- Fix archival memory search display with proper Python literal parsing
- Add interleaved notification checking during queue processing
- Filter out and auto-delete like notifications to improve performance
- Remove emojis from log messages for cleaner output
- Add pretty-printed panels for mentions, reasoning, tool calls, and results
- Improve error handling for various notification types
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updates the prompt to encourage single-post responses by default and only
use threaded replies when truly necessary (complex topics, explicit requests,
or structured answers). This should reduce the tendency to create long
threads for simple responses.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adds --no-git flag to bsky.py that skips git operations when exporting
agent state. This prevents the automatic git staging of agent backups
when the bot needs to export state (e.g., during halt operations).
Usage: python bsky.py --no-git
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add handle deduplication at the start of attach_user_blocks() to prevent
redundant API calls when the same user appears multiple times in a thread.
This helps reduce the spike in block list API calls.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Increases the maximum number of messages void can post in a single
threaded reply from 4 to 15, allowing for more comprehensive responses
to complex topics.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements a comprehensive queue management tool that allows:
- Viewing queue statistics across all directories (active, errors, no_reply)
- Listing notifications with filtering by handle
- Deleting all notifications from specific handles with dry-run support
- Force deletion option to skip confirmation prompts
Key features:
- Rich console output with formatted tables
- Safety features: dry-run mode and confirmation prompts
- Handles all queue directories (queue/, queue/errors/, queue/no_reply/)
- Proper error handling and validation
- Updated CLAUDE.md with usage examples
This tool helps manage notification queue buildup from bots and spam accounts,
complementing the new ignore_notification tool for proactive filtering.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements a new tool that allows the agent to explicitly ignore notifications
without creating a reply. This is particularly useful for filtering out bot
interactions or spam.
Key features:
- New ignore_notification tool with reason and category tracking
- Conflict detection if agent calls both reply and ignore tools
- Ignored notifications are deleted from queue (not moved to no_reply)
- Proper logging and tracking of ignored notifications
The tool helps the agent make deliberate decisions about which notifications
to engage with, improving interaction quality.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create queue/no_reply/ directory structure
- Modify process_mention to return "no_reply" when no reply is generated
- Update queue processing to move messages to no_reply/ folder
- Mark no_reply messages as processed to prevent reprocessing
- Update function documentation
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace deprecated bluesky_reply instruction with add_post_to_bluesky_reply_thread
- Provide clear guidance on atomic threading approach (multiple calls = thread)
- Add testing mode with --test flag to prevent actual posting and queue deletion
- Implement duplicate detection in queue to prevent reprocessing in test mode
- Update tool detection to terminate bot if deprecated bluesky_reply is used
- Add comprehensive testing mode logging with 🧪 indicators
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed process_mention to return False instead of True when no
add_post_to_bluesky_reply_thread tool calls are found. This ensures
that notifications remain in the queue for retry if the agent doesn't
generate a response, rather than being discarded.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove bluesky_reply tool to eliminate confusion with threading approach
- Add new add_post_to_bluesky_reply_thread tool for building reply threads atomically
- Each call adds a single post to the reply thread queue
- Handler (bsky.py) manages actual thread state and AT Protocol threading
- Better error recovery: individual post failures don't affect entire thread
- Added TOOL_CHANGELOG.md to document changes for agent migration
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add quote removal function to strip double quotes from AI responses before posting to prevent quoted text from appearing in posts. Only removes double quotes to preserve contractions and single quotes.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add user_note_append: Append text to user memory blocks
- Add user_note_replace: Find and replace text in blocks
- Add user_note_set: Completely set block content
- Add user_note_view: View block content
These tools provide fine-grained control over user-specific
memory blocks, allowing the agent to view, append, replace,
or completely rewrite user information as needed.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- user_note_append: Appends text to a user's memory block
- user_note_replace: Replaces specific text within a user's memory block
- user_note_set: Sets the complete content of a user's memory block
All tools handle block creation and attachment automatically.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
When a halt command is received, the bot now properly deletes the queue file
before terminating. This prevents the halt message from being reprocessed
when the bot restarts, which could cause an infinite halt loop.
Changes:
- Added queue_filepath parameter to process_mention()
- Delete queue file and mark notification as processed before exit(0)
- Updated all process_mention() calls to pass the filepath
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Show full reasoning messages without truncation
- Display bluesky_reply messages with content preview and language
- Show archival_memory_search queries clearly
- Display update_block operations with block name and value preview
- Enhanced tool result logging with success/error indicators
- Add specific formatting for known tool types
- Provide meaningful summaries for tool operations
This makes the bot's operation much more transparent and easier to debug.
- Replace loop with first successful candidate selection to avoid sending multiple replies
- Remove iteration logic that was causing duplicate responses when agent had multiple successful tool calls
- Update logging to show when additional candidates are skipped
- Simplify response handling to single attempt instead of retry loop
- Maintain support for both single replies and threaded replies (1-4 messages)
This fixes the issue where agents making multiple successful bluesky_reply tool calls
would send duplicate responses to the same user.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Only process bluesky_reply tool calls with status: "success"
- Skip tool calls with status: "error" to prevent sending failed replies
- Add two-pass processing: collect tool results first, then filter tool calls
- Increase log preview content from 100 to 150 characters for better visibility
- Add clear warning messages when skipping failed or unknown status tool calls
- Prevent sending replies that failed validation (e.g. >300 char limit)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace synchronous agents.messages.create with create_stream
- Add step streaming with max_steps=100 for better responsiveness
- Increase client timeout from 5 to 10 minutes
- Add condensed info-level logging for streaming chunks with emojis
- Add debug-level logging for full chunk details
- Maintain backward compatibility with existing response handling
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Changed order to fetch new notifications from server first
- Then queue new notifications with priority prefixes
- Finally process entire queue (old + new) in priority order
This ensures high-priority notifications (like those from cameron.pfiffer.org)
are discovered and queued immediately rather than waiting behind older messages.
🤖 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>
- 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>
Replace Rich panel formatting with simple text output using underscores
for titles. This provides a cleaner, more minimal logging style without
external dependencies.
Changes:
- Remove all Rich imports (Panel, Console, Table, Text)
- Replace panel displays with title + underscores format
- Remove --rich command line option
- Update log_with_panel to use simple print statements
- Remove USE_RICH and console global variables
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace plain text reply thread with Rich panels for better formatting
- Hide verbose log messages by changing to debug level
- Filter out usage_statistics and stop_reason message types
- Clean up tool result displays for bluesky posts
- Skip archival_memory_insert result displays (always None)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Rich panel formatting for all logs when --rich flag is used
- Add --reasoning flag to control reasoning display and log level
- Add --simple-logs flag for cleaner log format without timestamps
- Fix archival memory search display with proper Python literal parsing
- Add interleaved notification checking during queue processing
- Filter out and auto-delete like notifications to improve performance
- Remove emojis from log messages for cleaner output
- Add pretty-printed panels for mentions, reasoning, tool calls, and results
- Improve error handling for various notification types
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updates the prompt to encourage single-post responses by default and only
use threaded replies when truly necessary (complex topics, explicit requests,
or structured answers). This should reduce the tendency to create long
threads for simple responses.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adds --no-git flag to bsky.py that skips git operations when exporting
agent state. This prevents the automatic git staging of agent backups
when the bot needs to export state (e.g., during halt operations).
Usage: python bsky.py --no-git
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements a comprehensive queue management tool that allows:
- Viewing queue statistics across all directories (active, errors, no_reply)
- Listing notifications with filtering by handle
- Deleting all notifications from specific handles with dry-run support
- Force deletion option to skip confirmation prompts
Key features:
- Rich console output with formatted tables
- Safety features: dry-run mode and confirmation prompts
- Handles all queue directories (queue/, queue/errors/, queue/no_reply/)
- Proper error handling and validation
- Updated CLAUDE.md with usage examples
This tool helps manage notification queue buildup from bots and spam accounts,
complementing the new ignore_notification tool for proactive filtering.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements a new tool that allows the agent to explicitly ignore notifications
without creating a reply. This is particularly useful for filtering out bot
interactions or spam.
Key features:
- New ignore_notification tool with reason and category tracking
- Conflict detection if agent calls both reply and ignore tools
- Ignored notifications are deleted from queue (not moved to no_reply)
- Proper logging and tracking of ignored notifications
The tool helps the agent make deliberate decisions about which notifications
to engage with, improving interaction quality.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create queue/no_reply/ directory structure
- Modify process_mention to return "no_reply" when no reply is generated
- Update queue processing to move messages to no_reply/ folder
- Mark no_reply messages as processed to prevent reprocessing
- Update function documentation
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace deprecated bluesky_reply instruction with add_post_to_bluesky_reply_thread
- Provide clear guidance on atomic threading approach (multiple calls = thread)
- Add testing mode with --test flag to prevent actual posting and queue deletion
- Implement duplicate detection in queue to prevent reprocessing in test mode
- Update tool detection to terminate bot if deprecated bluesky_reply is used
- Add comprehensive testing mode logging with 🧪 indicators
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Changed process_mention to return False instead of True when no
add_post_to_bluesky_reply_thread tool calls are found. This ensures
that notifications remain in the queue for retry if the agent doesn't
generate a response, rather than being discarded.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove bluesky_reply tool to eliminate confusion with threading approach
- Add new add_post_to_bluesky_reply_thread tool for building reply threads atomically
- Each call adds a single post to the reply thread queue
- Handler (bsky.py) manages actual thread state and AT Protocol threading
- Better error recovery: individual post failures don't affect entire thread
- Added TOOL_CHANGELOG.md to document changes for agent migration
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add quote removal function to strip double quotes from AI responses before posting to prevent quoted text from appearing in posts. Only removes double quotes to preserve contractions and single quotes.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add user_note_append: Append text to user memory blocks
- Add user_note_replace: Find and replace text in blocks
- Add user_note_set: Completely set block content
- Add user_note_view: View block content
These tools provide fine-grained control over user-specific
memory blocks, allowing the agent to view, append, replace,
or completely rewrite user information as needed.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- user_note_append: Appends text to a user's memory block
- user_note_replace: Replaces specific text within a user's memory block
- user_note_set: Sets the complete content of a user's memory block
All tools handle block creation and attachment automatically.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
When a halt command is received, the bot now properly deletes the queue file
before terminating. This prevents the halt message from being reprocessed
when the bot restarts, which could cause an infinite halt loop.
Changes:
- Added queue_filepath parameter to process_mention()
- Delete queue file and mark notification as processed before exit(0)
- Updated all process_mention() calls to pass the filepath
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Show full reasoning messages without truncation
- Display bluesky_reply messages with content preview and language
- Show archival_memory_search queries clearly
- Display update_block operations with block name and value preview
- Enhanced tool result logging with success/error indicators
- Add specific formatting for known tool types
- Provide meaningful summaries for tool operations
This makes the bot's operation much more transparent and easier to debug.
- Replace loop with first successful candidate selection to avoid sending multiple replies
- Remove iteration logic that was causing duplicate responses when agent had multiple successful tool calls
- Update logging to show when additional candidates are skipped
- Simplify response handling to single attempt instead of retry loop
- Maintain support for both single replies and threaded replies (1-4 messages)
This fixes the issue where agents making multiple successful bluesky_reply tool calls
would send duplicate responses to the same user.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Only process bluesky_reply tool calls with status: "success"
- Skip tool calls with status: "error" to prevent sending failed replies
- Add two-pass processing: collect tool results first, then filter tool calls
- Increase log preview content from 100 to 150 characters for better visibility
- Add clear warning messages when skipping failed or unknown status tool calls
- Prevent sending replies that failed validation (e.g. >300 char limit)
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace synchronous agents.messages.create with create_stream
- Add step streaming with max_steps=100 for better responsiveness
- Increase client timeout from 5 to 10 minutes
- Add condensed info-level logging for streaming chunks with emojis
- Add debug-level logging for full chunk details
- Maintain backward compatibility with existing response handling
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Changed order to fetch new notifications from server first
- Then queue new notifications with priority prefixes
- Finally process entire queue (old + new) in priority order
This ensures high-priority notifications (like those from cameron.pfiffer.org)
are discovered and queued immediately rather than waiting behind older messages.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>