a digital person for bluesky

Add X downrank system and enhanced thread context handling

- 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>

Changed files
+106 -14
+29
CLAUDE.md
··· 47 ac && python register_tools.py my_agent_name 48 ``` 49 50 ### Creating Research Agents 51 ```bash 52 ac && python create_profile_researcher.py ··· 91 - `agent_response_{mention_id}.json` - Complete agent interaction including prompt, reasoning, tool calls, and responses 92 93 This debug data is especially useful for analyzing how different conversation types (including Grok interactions) are handled. 94 95 **Common Issues:** 96 - **Incomplete Thread Context**: X API's conversation search may miss recent tweets in long conversations. The bot attempts to fetch missing referenced tweets directly.
··· 47 ac && python register_tools.py my_agent_name 48 ``` 49 50 + ### Managing X Bot 51 + 52 + ```bash 53 + # Run X bot main loop 54 + ac && python x.py bot 55 + 56 + # Run in testing mode (no actual posts) 57 + ac && python x.py bot --test 58 + 59 + # Queue mentions only (no processing) 60 + ac && python x.py queue 61 + 62 + # Process queued mentions only 63 + ac && python x.py process 64 + 65 + # View downranked users (10% response rate) 66 + ac && python x.py downrank list 67 + ``` 68 + 69 ### Creating Research Agents 70 ```bash 71 ac && python create_profile_researcher.py ··· 110 - `agent_response_{mention_id}.json` - Complete agent interaction including prompt, reasoning, tool calls, and responses 111 112 This debug data is especially useful for analyzing how different conversation types (including Grok interactions) are handled. 113 + 114 + ### X Downrank System 115 + 116 + The X bot includes a downrank system to manage response frequency for specific users: 117 + 118 + - **File**: `x_downrank_users.txt` - Contains user IDs (one per line) that should be responded to less frequently 119 + - **Response Rate**: Downranked users receive responses only 10% of the time 120 + - **Format**: One user ID per line, comments start with `#` 121 + - **Logging**: All downrank decisions are logged for analysis 122 + - **Use Case**: Managing interactions with AI bots like Grok to prevent excessive back-and-forth 123 124 **Common Issues:** 125 - **Incomplete Thread Context**: X API's conversation search may miss recent tweets in long conversations. The bot attempts to fetch missing referenced tweets directly.
+71 -14
x.py
··· 4 import yaml 5 import json 6 import hashlib 7 - from typing import Optional, Dict, Any, List 8 from datetime import datetime 9 from pathlib import Path 10 from requests_oauthlib import OAuth1 ··· 26 X_CACHE_DIR = Path("x_cache") 27 X_PROCESSED_MENTIONS_FILE = Path("x_queue/processed_mentions.json") 28 X_LAST_SEEN_FILE = Path("x_queue/last_seen_id.json") 29 30 class XClient: 31 """X (Twitter) API client for fetching mentions and managing interactions.""" ··· 583 except Exception as e: 584 logger.error(f"Error saving processed mentions: {e}") 585 586 def save_mention_to_queue(mention: Dict): 587 """Save a mention to the queue directory for async processing.""" 588 try: ··· 1077 conversation_id = mention.get('conversation_id') 1078 in_reply_to_user_id = mention.get('in_reply_to_user_id') 1079 referenced_tweets = mention.get('referenced_tweets', []) 1080 1081 # Enhanced conversation tracking for debug - especially important for Grok handling 1082 logger.info(f"๐Ÿ” CONVERSATION DEBUG - Mention ID: {mention_id}") ··· 1808 # Use specific agent ID if provided, otherwise use from config 1809 agent_id = sys.argv[2] if len(sys.argv) > 2 else None 1810 test_letta_integration(agent_id) 1811 else: 1812 - print("Usage: python x.py [bot|loop|reply|me|search|queue|process|thread|letta]") 1813 - print(" bot - Run the main X bot (use --test for testing mode)") 1814 - print(" Example: python x.py bot --test") 1815 - print(" queue - Fetch and queue mentions only (no processing)") 1816 - print(" process - Process all queued mentions only (no fetching)") 1817 - print(" Example: python x.py process --test") 1818 - print(" loop - Run the old notification monitoring loop (deprecated)") 1819 - print(" reply - Reply to Cameron's specific post") 1820 - print(" me - Get authenticated user info and correct user ID") 1821 - print(" search - Test search-based mention detection") 1822 - print(" thread - Test thread context retrieval from queued mention") 1823 - print(" letta - Test sending thread context to Letta agent") 1824 - print(" Optional: python x.py letta <agent-id>") 1825 else: 1826 test_x_client()
··· 4 import yaml 5 import json 6 import hashlib 7 + import random 8 + from typing import Optional, Dict, Any, List, Set 9 from datetime import datetime 10 from pathlib import Path 11 from requests_oauthlib import OAuth1 ··· 27 X_CACHE_DIR = Path("x_cache") 28 X_PROCESSED_MENTIONS_FILE = Path("x_queue/processed_mentions.json") 29 X_LAST_SEEN_FILE = Path("x_queue/last_seen_id.json") 30 + X_DOWNRANK_USERS_FILE = Path("x_downrank_users.txt") 31 32 class XClient: 33 """X (Twitter) API client for fetching mentions and managing interactions.""" ··· 585 except Exception as e: 586 logger.error(f"Error saving processed mentions: {e}") 587 588 + def load_downrank_users() -> Set[str]: 589 + """Load the set of user IDs that should be downranked (responded to 10% of the time).""" 590 + try: 591 + if not X_DOWNRANK_USERS_FILE.exists(): 592 + return set() 593 + 594 + downrank_users = set() 595 + with open(X_DOWNRANK_USERS_FILE, 'r') as f: 596 + for line in f: 597 + line = line.strip() 598 + # Skip empty lines and comments 599 + if line and not line.startswith('#'): 600 + downrank_users.add(line) 601 + 602 + logger.info(f"Loaded {len(downrank_users)} downrank users") 603 + return downrank_users 604 + except Exception as e: 605 + logger.error(f"Error loading downrank users: {e}") 606 + return set() 607 + 608 + def should_respond_to_downranked_user(user_id: str, downrank_users: Set[str]) -> bool: 609 + """ 610 + Check if we should respond to a downranked user. 611 + Returns True 10% of the time for downranked users, True 100% of the time for others. 612 + """ 613 + if user_id not in downrank_users: 614 + return True 615 + 616 + # 10% chance for downranked users 617 + should_respond = random.random() < 0.1 618 + logger.info(f"Downranked user {user_id}: {'responding' if should_respond else 'skipping'} (10% chance)") 619 + return should_respond 620 + 621 def save_mention_to_queue(mention: Dict): 622 """Save a mention to the queue directory for async processing.""" 623 try: ··· 1112 conversation_id = mention.get('conversation_id') 1113 in_reply_to_user_id = mention.get('in_reply_to_user_id') 1114 referenced_tweets = mention.get('referenced_tweets', []) 1115 + 1116 + # Check downrank list - only respond to downranked users 10% of the time 1117 + downrank_users = load_downrank_users() 1118 + if not should_respond_to_downranked_user(str(author_id), downrank_users): 1119 + logger.info(f"๐Ÿ”ป Skipping downranked user {author_id} - not in 10% selection") 1120 + return "no_reply" 1121 1122 # Enhanced conversation tracking for debug - especially important for Grok handling 1123 logger.info(f"๐Ÿ” CONVERSATION DEBUG - Mention ID: {mention_id}") ··· 1849 # Use specific agent ID if provided, otherwise use from config 1850 agent_id = sys.argv[2] if len(sys.argv) > 2 else None 1851 test_letta_integration(agent_id) 1852 + elif sys.argv[1] == "downrank": 1853 + # View or manage downrank list 1854 + if len(sys.argv) > 2 and sys.argv[2] == "list": 1855 + downrank_users = load_downrank_users() 1856 + if downrank_users: 1857 + print(f"๐Ÿ“‹ Downrank users ({len(downrank_users)} total):") 1858 + for user_id in sorted(downrank_users): 1859 + print(f" - {user_id}") 1860 + else: 1861 + print("๐Ÿ“‹ No downrank users configured") 1862 + else: 1863 + print("Usage: python x.py downrank list") 1864 + print(" list - Show all downranked user IDs") 1865 + print(f" Edit {X_DOWNRANK_USERS_FILE} to modify the list") 1866 else: 1867 + print("Usage: python x.py [bot|loop|reply|me|search|queue|process|thread|letta|downrank]") 1868 + print(" bot - Run the main X bot (use --test for testing mode)") 1869 + print(" Example: python x.py bot --test") 1870 + print(" queue - Fetch and queue mentions only (no processing)") 1871 + print(" process - Process all queued mentions only (no fetching)") 1872 + print(" Example: python x.py process --test") 1873 + print(" downrank - Manage downrank users (10% response rate)") 1874 + print(" Example: python x.py downrank list") 1875 + print(" loop - Run the old notification monitoring loop (deprecated)") 1876 + print(" reply - Reply to Cameron's specific post") 1877 + print(" me - Get authenticated user info and correct user ID") 1878 + print(" search - Test search-based mention detection") 1879 + print(" thread - Test thread context retrieval from queued mention") 1880 + print(" letta - Test sending thread context to Letta agent") 1881 + print(" Optional: python x.py letta <agent-id>") 1882 else: 1883 test_x_client()
+6
x_downrank_users.txt
···
··· 1 + # X Downrank Users 2 + # User IDs in this file will only be responded to 10% of the time 3 + # Format: One user ID per line, comments start with # 4 + 5 + # Grok - xAI's AI assistant 6 + 1720665183188922368