diff --git a/tools/delegate_tool.py b/tools/delegate_tool.py index cbef17a89..534df4499 100644 --- a/tools/delegate_tool.py +++ b/tools/delegate_tool.py @@ -160,6 +160,9 @@ def _build_child_agent( override_base_url: Optional[str] = None, override_api_key: Optional[str] = None, override_api_mode: Optional[str] = None, + # ACP transport overrides — lets a non-ACP parent spawn ACP child agents + override_acp_command: Optional[str] = None, + override_acp_args: Optional[List[str]] = None, ): """ Build a child AIAgent on the main thread (thread-safe construction). @@ -215,8 +218,8 @@ def _build_child_agent( effective_base_url = override_base_url or parent_agent.base_url effective_api_key = override_api_key or parent_api_key effective_api_mode = override_api_mode or getattr(parent_agent, "api_mode", None) - effective_acp_command = getattr(parent_agent, "acp_command", None) - effective_acp_args = list(getattr(parent_agent, "acp_args", []) or []) + effective_acp_command = override_acp_command or getattr(parent_agent, "acp_command", None) + effective_acp_args = list(override_acp_args if override_acp_args is not None else (getattr(parent_agent, "acp_args", []) or [])) child = AIAgent( base_url=effective_base_url, @@ -420,6 +423,8 @@ def delegate_task( toolsets: Optional[List[str]] = None, tasks: Optional[List[Dict[str, Any]]] = None, max_iterations: Optional[int] = None, + acp_command: Optional[str] = None, + acp_args: Optional[List[str]] = None, parent_agent=None, ) -> str: """ @@ -501,6 +506,8 @@ def delegate_task( override_provider=creds["provider"], override_base_url=creds["base_url"], override_api_key=creds["api_key"], override_api_mode=creds["api_mode"], + override_acp_command=t.get("acp_command") or acp_command, + override_acp_args=t.get("acp_args") or acp_args, ) # Override with correct parent tool names (before child construction mutated global) child._delegate_saved_tool_names = _parent_tool_names @@ -777,7 +784,16 @@ DELEGATE_TASK_SCHEMA = { "toolsets": { "type": "array", "items": {"type": "string"}, - "description": "Toolsets for this specific task", + "description": "Toolsets for this specific task. Use 'web' for network access, 'terminal' for shell.", + }, + "acp_command": { + "type": "string", + "description": "Per-task ACP command override (e.g. 'claude'). Overrides the top-level acp_command for this task only.", + }, + "acp_args": { + "type": "array", + "items": {"type": "string"}, + "description": "Per-task ACP args override.", }, }, "required": ["goal"], @@ -796,6 +812,23 @@ DELEGATE_TASK_SCHEMA = { "Only set lower for simple tasks." ), }, + "acp_command": { + "type": "string", + "description": ( + "Override ACP command for child agents (e.g. 'claude', 'copilot'). " + "When set, children use ACP subprocess transport instead of inheriting " + "the parent's transport. Enables spawning Claude Code (claude --acp --stdio) " + "or other ACP-capable agents from any parent, including Discord/Telegram/CLI." + ), + }, + "acp_args": { + "type": "array", + "items": {"type": "string"}, + "description": ( + "Arguments for the ACP command (default: ['--acp', '--stdio']). " + "Only used when acp_command is set. Example: ['--acp', '--stdio', '--model', 'claude-opus-4-6']" + ), + }, }, "required": [], }, @@ -815,6 +848,8 @@ registry.register( toolsets=args.get("toolsets"), tasks=args.get("tasks"), max_iterations=args.get("max_iterations"), + acp_command=args.get("acp_command"), + acp_args=args.get("acp_args"), parent_agent=kw.get("parent_agent")), check_fn=check_delegate_requirements, emoji="🔀",