@@ -350,6 +350,7 @@ def main(self):
350350 self .args = args
351351 invocation_cmd = "praisonai"
352352 version_string = f"PraisonAI version { __version__ } "
353+
353354
354355 # Handle -p/--prompt flag - treat as direct prompt
355356 if getattr (args , 'prompt_flag' , None ):
@@ -393,6 +394,28 @@ def main(self):
393394 exit_code = AgentSchedulerHandler .handle_schedule_command (args , unknown_args , daemon_mode = daemon_mode )
394395
395396 sys .exit (exit_code )
397+
398+ # Handle backends command
399+ elif args .command == "backends" :
400+ from rich import print
401+ subcommand = unknown_args [0 ] if unknown_args and not unknown_args [0 ].startswith ('-' ) else None
402+
403+ if subcommand == "list" or subcommand is None :
404+ # List registered CLI backends
405+ try :
406+ from praisonai .cli_backends import list_cli_backends
407+ backends = list_cli_backends ()
408+ for backend in backends :
409+ print (backend )
410+ return ""
411+ except ImportError :
412+ print ("[red]CLI backends not available[/red]" )
413+ return None
414+ else :
415+ print (f"[red]Unknown backends subcommand: { subcommand } [/red]" )
416+ print ("Available subcommands: list" )
417+ return None
418+
396419 elif args .command .startswith ("tests.test" ) or args .command .startswith ("tests/test" ): # Argument used for testing purposes
397420 print ("test" )
398421 return "test"
@@ -875,7 +898,7 @@ def parse_args(self):
875898 return default_args
876899
877900 # Define special commands
878- special_commands = ['chat' , 'code' , 'call' , 'realtime' , 'train' , 'ui' , 'context' , 'research' , 'memory' , 'rules' , 'workflow' , 'hooks' , 'knowledge' , 'session' , 'tools' , 'todo' , 'docs' , 'mcp' , 'commit' , 'serve' , 'schedule' , 'skills' , 'profile' , 'eval' , 'agents' , 'run' , 'thinking' , 'compaction' , 'output' , 'deploy' , 'templates' , 'recipe' , 'endpoints' , 'audio' , 'embed' , 'embedding' , 'images' , 'moderate' , 'files' , 'batches' , 'vector-stores' , 'rerank' , 'ocr' , 'assistants' , 'fine-tuning' , 'completions' , 'messages' , 'guardrails' , 'rag' , 'videos' , 'a2a' , 'containers' , 'passthrough' , 'responses' , 'search' , 'realtime-api' , 'doctor' , 'registry' , 'package' , 'install' , 'uninstall' , 'acp' , 'debug' , 'lsp' , 'diag' , 'browser' , 'replay' , 'bot' , 'gateway' , 'sandbox' , 'wizard' , 'migrate' , 'security' , 'persistence' , 'paths' , 'claw' , 'github' , 'managed' , 'flow' , 'dashboard' ]
901+ special_commands = ['chat' , 'code' , 'call' , 'realtime' , 'train' , 'ui' , 'context' , 'research' , 'memory' , 'rules' , 'workflow' , 'hooks' , 'knowledge' , 'session' , 'tools' , 'todo' , 'docs' , 'mcp' , 'commit' , 'serve' , 'schedule' , 'skills' , 'profile' , 'eval' , 'agents' , 'run' , 'thinking' , 'compaction' , 'output' , 'deploy' , 'templates' , 'recipe' , 'endpoints' , 'audio' , 'embed' , 'embedding' , 'images' , 'moderate' , 'files' , 'batches' , 'vector-stores' , 'rerank' , 'ocr' , 'assistants' , 'fine-tuning' , 'completions' , 'messages' , 'guardrails' , 'rag' , 'videos' , 'a2a' , 'containers' , 'passthrough' , 'responses' , 'search' , 'realtime-api' , 'doctor' , 'registry' , 'package' , 'install' , 'uninstall' , 'acp' , 'debug' , 'lsp' , 'diag' , 'browser' , 'replay' , 'bot' , 'gateway' , 'sandbox' , 'wizard' , 'migrate' , 'security' , 'persistence' , 'paths' , 'claw' , 'github' , 'managed' , 'flow' , 'dashboard' , 'backends' ]
879902
880903 parser = argparse .ArgumentParser (prog = "praisonai" , description = "praisonAI command-line interface" )
881904 parser .add_argument ("--framework" , choices = ["crewai" , "autogen" , "praisonai" ], help = "Specify the framework" )
@@ -1057,9 +1080,23 @@ def parse_args(self):
10571080 # Sandbox Execution - secure command execution
10581081 parser .add_argument ("--sandbox" , type = str , choices = ["off" , "basic" , "strict" ], help = "Enable sandboxed command execution" )
10591082
1060- # External Agent - use external AI CLI tools
1061- parser .add_argument ("--external-agent" , type = str , choices = ["claude" , "gemini" , "codex" , "cursor" ],
1083+ # Backend group - mutually exclusive external agent and CLI backend options
1084+ backend_group = parser .add_mutually_exclusive_group ()
1085+ backend_group .add_argument ("--external-agent" , type = str , choices = ["claude" , "gemini" , "codex" , "cursor" ],
10621086 help = "Use external AI CLI tool (claude, gemini, codex, cursor)" )
1087+
1088+ # CLI Backend - delegate agent turns to CLI backend
1089+ # Dynamically populate choices from registered backends
1090+ try :
1091+ from praisonai .cli_backends import list_cli_backends
1092+ cli_backend_choices = list_cli_backends () or None
1093+ except ImportError :
1094+ cli_backend_choices = None
1095+
1096+ backend_group .add_argument ("--cli-backend" , type = str , choices = cli_backend_choices ,
1097+ help = "Delegate agent turns to a CLI backend (see praisonai backends list)" )
1098+
1099+ # External agent direct mode (not mutually exclusive with backend choice)
10631100 parser .add_argument ("--external-agent-direct" , action = "store_true" ,
10641101 help = "Use external agent as direct proxy (skip manager Agent delegation)" )
10651102
@@ -4507,6 +4544,14 @@ def level_based_approve(function_name, arguments, risk_level):
45074544
45084545 return result
45094546
4547+ # CLI Backend - delegate agent turns to external CLI tools
4548+ if hasattr (self , 'args' ) and getattr (self .args , 'cli_backend' , None ):
4549+ try :
4550+ from praisonai .cli_backends import resolve_cli_backend
4551+ agent_config ["cli_backend" ] = resolve_cli_backend (self .args .cli_backend )
4552+ except Exception as e :
4553+ self .logger .warning (f"Failed to resolve CLI backend '{ self .args .cli_backend } ': { e } " )
4554+
45104555 # Flow Display - Visual workflow tracking
45114556 if hasattr (self , 'args' ) and getattr (self .args , 'flow_display' , False ):
45124557 from .features .flow_display import FlowDisplayHandler
0 commit comments