Execute the subagent task and announce the result.
(
self,
task_id: str,
task: str,
label: str,
origin: dict[str, str],
)
| 90 | return f"Subagent [{display_label}] started (id: {task_id}). I'll notify you when it completes." |
| 91 | |
| 92 | async def _run_subagent( |
| 93 | self, |
| 94 | task_id: str, |
| 95 | task: str, |
| 96 | label: str, |
| 97 | origin: dict[str, str], |
| 98 | ) -> None: |
| 99 | """Execute the subagent task and announce the result.""" |
| 100 | logger.info(f"Subagent [{task_id}] starting task: {label}") |
| 101 | |
| 102 | try: |
| 103 | # Build subagent tools (no message tool, no spawn tool) |
| 104 | tools = ToolRegistry() |
| 105 | allowed_dir = self.workspace if self.restrict_to_workspace else None |
| 106 | tools.register(ReadFileTool(allowed_dir=allowed_dir)) |
| 107 | tools.register(WriteFileTool(allowed_dir=allowed_dir)) |
| 108 | tools.register(ListDirTool(allowed_dir=allowed_dir)) |
| 109 | tools.register( |
| 110 | ExecTool( |
| 111 | working_dir=str(self.workspace), |
| 112 | timeout=self.exec_config.timeout, |
| 113 | restrict_to_workspace=self.restrict_to_workspace, |
| 114 | ) |
| 115 | ) |
| 116 | tools.register(WebSearchTool(api_key=self.brave_api_key)) |
| 117 | tools.register(WebFetchTool()) |
| 118 | |
| 119 | # Build messages with subagent-specific prompt |
| 120 | system_prompt = self._build_subagent_prompt(task) |
| 121 | messages: list[dict[str, Any]] = [ |
| 122 | {"role": "system", "content": system_prompt}, |
| 123 | {"role": "user", "content": task}, |
| 124 | ] |
| 125 | |
| 126 | # Run agent loop (limited iterations) |
| 127 | max_iterations = 15 |
| 128 | iteration = 0 |
| 129 | final_result: str | None = None |
| 130 | |
| 131 | while iteration < max_iterations: |
| 132 | iteration += 1 |
| 133 | |
| 134 | response = await self.provider.chat( |
| 135 | messages=messages, |
| 136 | tools=tools.get_definitions(), |
| 137 | model=self.model, |
| 138 | ) |
| 139 | |
| 140 | if response.has_tool_calls: |
| 141 | # Add assistant message with tool calls |
| 142 | tool_call_dicts = [ |
| 143 | { |
| 144 | "id": tc.id, |
| 145 | "type": "function", |
| 146 | "function": { |
| 147 | "name": tc.name, |
| 148 | "arguments": json.dumps(tc.arguments), |
| 149 | }, |
no test coverage detected