#!/usr/bin/env python3 """ Agent-S Wrapper for OpenClaw Integration This script provides a simple interface for OpenClaw to invoke Agent-S for GUI automation tasks. """ import argparse import json import subprocess import sys import os import shutil def run_agent_s(task, max_steps=15, enable_reflection=True, enable_local_env=False): """ Execute an Agent-S task and return the result. Args: task: Natural language task description max_steps: Maximum number of steps (default: 15) enable_reflection: Enable reflection agent (default: True) enable_local_env: Enable local code execution (default: False, WARNING: executes arbitrary code) Returns: Dictionary with status and message """ # Path to agent_s executable - auto-detect or use environment variable agent_s_path = os.environ.get("AGENT_S_PATH") or shutil.which("agent_s") if not agent_s_path: return { "status": "error", "message": "agent_s not found in PATH. Install with: pip install gui-agents", "error": "agent_s executable not found" } # Build base command cmd = [ agent_s_path, "--provider", "anthropic", "--model", "claude-sonnet-4-5", "--model_temperature", "1.0", "--max_trajectory_length", str(max_steps), "--task", task, ] # Add optional grounding configuration from environment variables ground_url = os.environ.get("AGENT_S_GROUND_URL") ground_api_key = os.environ.get("AGENT_S_GROUND_API_KEY") ground_model = os.environ.get("AGENT_S_GROUND_MODEL", "ui-tars-1.5-7b") grounding_width = os.environ.get("AGENT_S_GROUNDING_WIDTH", "1920") grounding_height = os.environ.get("AGENT_S_GROUNDING_HEIGHT", "1080") if ground_url: cmd.extend(["--ground_provider", "huggingface"]) cmd.extend(["--ground_url", ground_url]) cmd.extend(["--ground_model", ground_model]) cmd.extend(["--grounding_width", grounding_width]) cmd.extend(["--grounding_height", grounding_height]) if ground_api_key: cmd.extend(["--ground_api_key", ground_api_key]) if enable_reflection: cmd.append("--enable_reflection") if enable_local_env: cmd.append("--enable_local_env") try: # Run Agent-S print(f"Starting Agent-S with task: {task}", file=sys.stderr) print(f"Command: {' '.join(cmd)}", file=sys.stderr) # Agent-S can take 2-5 minutes for complex tasks (15 steps max) # Don't capture output - let it stream to allow real-time GUI interaction result = subprocess.run( cmd, capture_output=False, # Changed: let output stream text=True, timeout=600 # 10 minute timeout ) if result.returncode == 0: return { "status": "success", "message": f"Agent-S completed the task: {task}", "logs_directory": os.path.expanduser("~/workspace/Agent-S/logs/"), "note": "Output was streamed to terminal. Check logs for details." } else: return { "status": "error", "message": f"Agent-S failed with return code {result.returncode}", "logs_directory": os.path.expanduser("~/workspace/Agent-S/logs/"), "note": "Check logs for error details." } except subprocess.TimeoutExpired: return { "status": "error", "message": f"Agent-S timed out after 10 minutes for task: {task}", "error": "Timeout expired" } except Exception as e: return { "status": "error", "message": f"Failed to execute Agent-S: {str(e)}", "error": str(e) } def main(): parser = argparse.ArgumentParser( description="OpenClaw wrapper for Agent-S GUI automation" ) parser.add_argument( "task", type=str, help="Natural language description of the GUI task to perform" ) parser.add_argument( "--max-steps", type=int, default=15, help="Maximum number of agent steps (default: 15)" ) parser.add_argument( "--enable-reflection", action="store_true", default=True, help="Enable reflection agent for better performance" ) parser.add_argument( "--no-reflection", action="store_false", dest="enable_reflection", help="Disable reflection agent" ) parser.add_argument( "--enable-local-env", action="store_true", default=False, help="Enable local code execution (WARNING: executes arbitrary code)" ) parser.add_argument( "--json", action="store_true", help="Output result as JSON" ) args = parser.parse_args() # Execute Agent-S task result = run_agent_s( task=args.task, max_steps=args.max_steps, enable_reflection=args.enable_reflection, enable_local_env=args.enable_local_env ) # Output result if args.json: print(json.dumps(result, indent=2)) else: if result["status"] == "success": print(f"✓ {result['message']}") if result.get("output"): print(f"\nOutput:\n{result['output']}") else: print(f"✗ {result['message']}") if result.get("error"): print(f"\nError:\n{result['error']}", file=sys.stderr) sys.exit(1) if __name__ == "__main__": main()