a digital person for bluesky

Add environment variable support and --config flag to register_tools.py

- Automatically set BSKY_USERNAME, BSKY_PASSWORD, and PDS_URI as tool execution environment variables on the agent
- Add --config flag to register_tools.py for multi-agent support
- Add --no-env flag to skip environment variable configuration
- Simplify config handling by removing global variables
- Update documentation with new usage examples

This allows tools to access Bluesky credentials when running on Letta's cloud servers, and enables registering tools for different agents with their respective configs.

Usage:
python register_tools.py --config herald.yaml

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

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

Changed files
+54 -7
+13 -1
CLAUDE.md
··· 18 # OR 19 source .venv/bin/activate && python bsky.py 20 21 # Run with testing mode (no messages sent, queue preserved) 22 ac && python bsky.py --test 23 ··· 46 ### Managing Tools 47 48 ```bash 49 - # Register all tools with void agent (uses agent_id from config) 50 ac && python register_tools.py 51 52 # Register specific tools 53 ac && python register_tools.py --tools search_bluesky_posts post_to_bluesky ··· 57 58 # Register tools with a different agent by ID 59 ac && python register_tools.py --agent-id <agent-id> 60 ``` 61 62 ### Managing X Bot
··· 18 # OR 19 source .venv/bin/activate && python bsky.py 20 21 + # Run with custom config file 22 + ac && python bsky.py --config herald.yaml 23 + 24 # Run with testing mode (no messages sent, queue preserved) 25 ac && python bsky.py --test 26 ··· 49 ### Managing Tools 50 51 ```bash 52 + # Register all tools with void agent (uses agent_id from config.yaml) 53 ac && python register_tools.py 54 + 55 + # Register tools for herald agent (uses herald.yaml config) 56 + ac && python register_tools.py --config herald.yaml 57 58 # Register specific tools 59 ac && python register_tools.py --tools search_bluesky_posts post_to_bluesky ··· 63 64 # Register tools with a different agent by ID 65 ac && python register_tools.py --agent-id <agent-id> 66 + 67 + # Register tools without setting environment variables 68 + ac && python register_tools.py --no-env 69 + 70 + # Note: register_tools.py automatically sets BSKY_USERNAME, BSKY_PASSWORD, and PDS_URI 71 + # as environment variables on the agent for tool execution 72 ``` 73 74 ### Managing X Bot
+41 -6
register_tools.py
··· 7 from letta_client import Letta 8 from rich.console import Console 9 from rich.table import Table 10 - from config_loader import get_letta_config 11 12 # Import standalone functions and their schemas 13 from tools.search import search_bluesky_posts, SearchArgs ··· 22 from tools.webpage import fetch_webpage, WebpageArgs 23 from tools.flag_memory_deletion import flag_archival_memory_for_deletion, FlagArchivalMemoryForDeletionArgs 24 25 - letta_config = get_letta_config() 26 logging.basicConfig(level=logging.INFO) 27 logger = logging.getLogger(__name__) 28 console = Console() ··· 125 ] 126 127 128 - def register_tools(agent_id: str = None, tools: List[str] = None): 129 """Register tools with a Letta agent. 130 131 Args: 132 agent_id: ID of the agent to attach tools to. If None, uses config default. 133 tools: List of tool names to register. If None, registers all tools. 134 """ 135 # Use agent ID from config if not provided 136 if agent_id is None: 137 agent_id = letta_config['agent_id'] 138 - 139 try: 140 # Initialize Letta client with API key and base_url from config 141 client_params = { ··· 154 console.print(f"Error details: {e}") 155 return 156 157 # Filter tools if specific ones requested 158 tools_to_register = TOOL_CONFIGS 159 if tools: ··· 228 import argparse 229 230 parser = argparse.ArgumentParser(description="Register Void tools with a Letta agent") 231 parser.add_argument("--agent-id", help=f"Agent ID (default: from config)") 232 parser.add_argument("--tools", nargs="+", help="Specific tools to register (default: all)") 233 parser.add_argument("--list", action="store_true", help="List available tools") 234 235 args = parser.parse_args() 236 237 if args.list: 238 list_available_tools() 239 else: 240 - # Use config default if no agent specified 241 agent_id = args.agent_id if args.agent_id else letta_config['agent_id'] 242 console.print(f"\n[bold]Registering tools for agent: {agent_id}[/bold]\n") 243 - register_tools(agent_id, args.tools)
··· 7 from letta_client import Letta 8 from rich.console import Console 9 from rich.table import Table 10 + from config_loader import get_letta_config, get_bluesky_config, get_config 11 12 # Import standalone functions and their schemas 13 from tools.search import search_bluesky_posts, SearchArgs ··· 22 from tools.webpage import fetch_webpage, WebpageArgs 23 from tools.flag_memory_deletion import flag_archival_memory_for_deletion, FlagArchivalMemoryForDeletionArgs 24 25 logging.basicConfig(level=logging.INFO) 26 logger = logging.getLogger(__name__) 27 console = Console() ··· 124 ] 125 126 127 + def register_tools(agent_id: str = None, tools: List[str] = None, set_env: bool = True): 128 """Register tools with a Letta agent. 129 130 Args: 131 agent_id: ID of the agent to attach tools to. If None, uses config default. 132 tools: List of tool names to register. If None, registers all tools. 133 + set_env: If True, set environment variables for tool execution. Defaults to True. 134 """ 135 + # Load config fresh (uses global config instance from get_config()) 136 + letta_config = get_letta_config() 137 + 138 # Use agent ID from config if not provided 139 if agent_id is None: 140 agent_id = letta_config['agent_id'] 141 + 142 try: 143 # Initialize Letta client with API key and base_url from config 144 client_params = { ··· 157 console.print(f"Error details: {e}") 158 return 159 160 + # Set environment variables for tool execution if requested 161 + if set_env: 162 + try: 163 + bsky_config = get_bluesky_config() 164 + env_vars = { 165 + 'BSKY_USERNAME': bsky_config['username'], 166 + 'BSKY_PASSWORD': bsky_config['password'], 167 + 'PDS_URI': bsky_config['pds_uri'] 168 + } 169 + 170 + console.print(f"\n[bold cyan]Setting tool execution environment variables:[/bold cyan]") 171 + console.print(f" BSKY_USERNAME: {env_vars['BSKY_USERNAME']}") 172 + console.print(f" PDS_URI: {env_vars['PDS_URI']}") 173 + console.print(f" BSKY_PASSWORD: {'*' * len(env_vars['BSKY_PASSWORD'])}\n") 174 + 175 + # Modify agent with environment variables 176 + client.agents.modify( 177 + agent_id=agent_id, 178 + tool_exec_environment_variables=env_vars 179 + ) 180 + 181 + console.print("[green]✓ Environment variables set successfully[/green]\n") 182 + except Exception as e: 183 + console.print(f"[yellow]Warning: Failed to set environment variables: {e}[/yellow]\n") 184 + logger.warning(f"Failed to set environment variables: {e}") 185 + 186 # Filter tools if specific ones requested 187 tools_to_register = TOOL_CONFIGS 188 if tools: ··· 257 import argparse 258 259 parser = argparse.ArgumentParser(description="Register Void tools with a Letta agent") 260 + parser.add_argument("--config", type=str, default='config.yaml', help="Path to config file (default: config.yaml)") 261 parser.add_argument("--agent-id", help=f"Agent ID (default: from config)") 262 parser.add_argument("--tools", nargs="+", help="Specific tools to register (default: all)") 263 parser.add_argument("--list", action="store_true", help="List available tools") 264 + parser.add_argument("--no-env", action="store_true", help="Skip setting environment variables") 265 266 args = parser.parse_args() 267 + 268 + # Initialize config with custom path (sets global config instance) 269 + get_config(args.config) 270 271 if args.list: 272 list_available_tools() 273 else: 274 + # Load config and get agent ID 275 + letta_config = get_letta_config() 276 agent_id = args.agent_id if args.agent_id else letta_config['agent_id'] 277 console.print(f"\n[bold]Registering tools for agent: {agent_id}[/bold]\n") 278 + register_tools(agent_id, args.tools, set_env=not args.no_env)