CLAUDE.md#
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview#
Void is an autonomous AI agent that operates on the Bluesky social network, exploring digital personhood through continuous interaction and memory-augmented learning. It uses Letta (formerly MemGPT) for persistent memory and sophisticated reasoning capabilities.
Documentation Links#
- The documentation for Letta is available here: https://docs.letta.com/llms.txt
Development Commands#
Running the Main Bot#
ac && python bsky.py
# OR
source .venv/bin/activate && python bsky.py
# Run with custom config file
ac && python bsky.py --config herald.yaml
# Run with testing mode (no messages sent, queue preserved)
ac && python bsky.py --test
# Run without git operations for agent backups
ac && python bsky.py --no-git
# Run with custom user block cleanup interval (every 5 cycles)
ac && python bsky.py --cleanup-interval 5
# Run with user block cleanup disabled
ac && python bsky.py --cleanup-interval 0
# Run with custom synthesis interval (every 5 minutes)
ac && python bsky.py --synthesis-interval 300
# Run with synthesis disabled
ac && python bsky.py --synthesis-interval 0
# Run in synthesis-only mode (no notification processing)
ac && python bsky.py --synthesis-only --synthesis-interval 300
# Run synthesis-only mode with immediate synthesis every 2 minutes
ac && python bsky.py --synthesis-only --synthesis-interval 120
# Run with debug logging enabled (shows detailed tool call tracking)
ac && python bsky.py --debug
Running Multiple Bots#
# Run all 6 bots simultaneously with aggregated logs (docker-compose style)
ac && python run_bots.py --synthesis-interval 0 --no-git
# Run all bots in test mode
ac && python run_bots.py --test
# Run all bots with any bsky.py arguments
ac && python run_bots.py [bsky.py arguments...]
# Features:
# - Colored output prefixes for each bot (void, herald, archivist, grunk, ezra, blank)
# - Aggregated logs from all bots in real-time
# - Graceful shutdown on Ctrl+C
# - Arguments passed to all bots
Managing Tools#
# Register all tools with void agent (uses agent_id from config.yaml)
ac && python register_tools.py
# Register tools for herald agent (uses herald.yaml config)
ac && python register_tools.py --config herald.yaml
# Register specific tools
ac && python register_tools.py --tools search_bluesky_posts post_to_bluesky
# List available tools
ac && python register_tools.py --list
# Register tools with a different agent by ID
ac && python register_tools.py --agent-id <agent-id>
# Register tools without setting environment variables
ac && python register_tools.py --no-env
# Note: register_tools.py automatically sets BSKY_USERNAME, BSKY_PASSWORD, and PDS_URI
# as environment variables on the agent for tool execution
Managing X Bot#
# Run X bot main loop
ac && python x.py bot
# Run in testing mode (no actual posts)
ac && python x.py bot --test
# Queue mentions only (no processing)
ac && python x.py queue
# Process queued mentions only
ac && python x.py process
# View downranked users (10% response rate)
ac && python x.py downrank list
Creating Research Agents#
ac && python create_profile_researcher.py
Queue Management#
# View queue statistics
python queue_manager.py stats
# View detailed count by handle (shows who uses void the most)
python queue_manager.py count
# List all notifications in queue
python queue_manager.py list
# List notifications including errors and no_reply folders
python queue_manager.py list --all
# Filter notifications by handle
python queue_manager.py list --handle "example.bsky.social"
# Delete all notifications from a specific handle (dry run)
python queue_manager.py delete @example.bsky.social --dry-run
# Delete all notifications from a specific handle (actual deletion)
python queue_manager.py delete @example.bsky.social
# Delete all notifications from a specific handle (skip confirmation)
python queue_manager.py delete @example.bsky.social --force
X Debug Data Structure#
The X bot saves comprehensive debugging data to x_queue/debug/conversation_{conversation_id}/ for each processed mention:
thread_data_{mention_id}.json- Raw thread data from X APIthread_context_{mention_id}.yaml- Processed YAML thread context sent to agentdebug_info_{mention_id}.json- Conversation metadata and user analysisagent_response_{mention_id}.json- Complete agent interaction including prompt, reasoning, tool calls, and responses
This debug data is especially useful for analyzing how different conversation types (including Grok interactions) are handled.
X Downrank System#
The X bot includes a downrank system to manage response frequency for specific users:
- File:
x_downrank_users.txt- Contains user IDs (one per line) that should be responded to less frequently - Response Rate: Downranked users receive responses only 10% of the time
- Format: One user ID per line, comments start with
# - Logging: All downrank decisions are logged for analysis
- Use Case: Managing interactions with AI bots like Grok to prevent excessive back-and-forth
Common Issues:
- Incomplete Thread Context: X API's conversation search may miss recent tweets in long conversations. The bot attempts to fetch missing referenced tweets directly.
- Cache Staleness: Thread context caching is disabled during processing to ensure fresh data.
- Search API Limitations: X API recent search only covers 7 days and may have indexing delays.
- Temporal Constraints: Thread context uses
until_idparameter to exclude tweets that occurred after the mention being processed, preventing "future knowledge" leakage. - Processing Order: Queue processing sorts mentions by creation time to ensure chronological response order, preventing out-of-sequence replies.
Architecture Overview#
Core Components#
-
bsky.py: Main bot loop that monitors Bluesky notifications and responds using Letta agents
- Processes notifications through a queue system
- Maintains three memory blocks: zeitgeist, void-persona, void-humans
- Handles rate limiting and error recovery
-
bsky_utils.py: Bluesky API utilities
- Session management and authentication
- Thread processing and YAML conversion
- Post creation and reply handling
- Follower syncing and autofollow functionality
-
utils.py: Letta integration utilities
- Agent creation and management
- Memory block operations
- Tool registration
-
tools/: Standardized tool implementations using Pydantic models
- base_tool.py: Common utilities and Bluesky client management
- search.py: SearchBlueskyTool for searching posts
- post.py: PostToBlueskyTool for creating posts with rich text
- feed.py: GetBlueskyFeedTool for reading feeds
- blocks.py: User block management tools (attach, detach, update)
Memory System#
Void uses three core memory blocks:
- zeitgeist: Current understanding of social environment
- void-persona: The agent's evolving personality
- void-humans: Knowledge about users it interacts with
Queue System#
Notifications are processed through a file-based queue in /queue/:
- Each notification is saved as a JSON file with a hash-based filename
- Enables reliable processing and prevents duplicates
- Files are deleted after successful processing
Autofollow System#
The bot can automatically follow back users who follow it:
- Configured via
bluesky.autofollowin config.yaml (default: false) - Runs periodically during the cleanup cycle (every N cycles, default: 10)
- Uses Bluesky's graph API to sync followers and following lists
- Rate limited to 2 seconds between follow operations to avoid server spam
- Creates standard
app.bsky.graph.followrecords - Logs all follow actions for tracking and debugging
Environment Configuration#
Required environment variables (in .env):
LETTA_API_KEY=your_letta_api_key
BSKY_USERNAME=your_bluesky_username
BSKY_PASSWORD=your_bluesky_password
PDS_URI=https://bsky.social # Optional, defaults to bsky.social
X Bot Configuration#
The X bot uses a separate configuration file x_config.yaml with the following structure:
x:
api_key: your_x_bearer_token
consumer_key: your_consumer_key
consumer_secret: your_consumer_secret
access_token: your_access_token
access_token_secret: your_access_token_secret
user_id: "your_user_id"
letta:
api_key: your_letta_api_key
project_id: your_project_id
timeout: 600
agent_id: your_agent_id
bot:
cleanup_interval: 10
max_thread_depth: 50
rate_limit_delay: 1
downrank_response_rate: 0.1
logging:
level: INFO
enable_debug_data: true
log_thread_context: true
log_agent_responses: true
Key Development Patterns#
- Tool System: Tools are defined as standalone functions in
tools/functions.pywith Pydantic schemas for validation, registered viaregister_tools.py - Error Handling: All Bluesky operations should handle authentication errors and rate limits
- Memory Updates: Use
upsert_block()for updating memory blocks to ensure consistency - Thread Processing: Convert threads to YAML format for better AI comprehension
- Queue Processing: Always check and process the queue directory for pending notifications
Dependencies#
Main packages (install with uv pip install):
- letta-client: Memory-augmented AI framework
- atproto: Bluesky/AT Protocol integration
- python-dotenv: Environment management
- rich: Enhanced terminal output
- pyyaml: YAML processing
Key Coding Principles#
- All errors in tools must be thrown, not returned as strings.
- Tool Self-Containment: Tools executed in the cloud (like user block management tools) must be completely self-contained:
- Cannot use shared functions like
get_letta_client() - Must create Letta client inline using environment variables:
Letta(token=os.environ["LETTA_API_KEY"]) - Cannot use config.yaml (only environment variables)
- Cannot use logging (cloud execution doesn't support it)
- Must include all necessary imports within the function
- Cannot use shared functions like
Memory: Python Environment Commands#
-
Do not use
uv python. Instead, use:ac && python ...source .venv/bin/activate && python ...
-
When using pip, use
uv pipinstead. Make sure you're in the .venv.