Execute a single LLM step with tool calling loop. Prepares messages and tools, then delegates to multi_step_tool_call_loop for the actual LLM interaction. Handles system prompt resolution and effective tool configuration. Args: instruction: The prompt/in
(
self,
instruction: str,
prev_output: str, # noqa: ARG002 - kept for API compatibility, use context["prev_output"] instead
step_id: Union[int, str],
args: EffectiveArgs,
logger: Logger,
context: Optional[Dict[str, Any]] = None,
system_prompt: Optional[str] = None,
step_config: Optional[Dict[str, Any]] = None,
)
| 192 | return os.path.join(host_ws, "sessions", sess_key, vpath.lstrip("/")) |
| 193 | |
| 194 | def execute_llm_step( |
| 195 | self, |
| 196 | instruction: str, |
| 197 | prev_output: str, # noqa: ARG002 - kept for API compatibility, use context["prev_output"] instead |
| 198 | step_id: Union[int, str], |
| 199 | args: EffectiveArgs, |
| 200 | logger: Logger, |
| 201 | context: Optional[Dict[str, Any]] = None, |
| 202 | system_prompt: Optional[str] = None, |
| 203 | step_config: Optional[Dict[str, Any]] = None, |
| 204 | ) -> Tuple[Any, int]: |
| 205 | """Execute a single LLM step with tool calling loop. |
| 206 | |
| 207 | Prepares messages and tools, then delegates to multi_step_tool_call_loop |
| 208 | for the actual LLM interaction. Handles system prompt resolution and |
| 209 | effective tool configuration. |
| 210 | |
| 211 | Args: |
| 212 | instruction: The prompt/instruction for this step. |
| 213 | prev_output: Output from the previous step (for context). |
| 214 | step_id: Identifier for this step in the workflow. |
| 215 | args: Effective arguments with model configuration. |
| 216 | logger: Logger instance for output. |
| 217 | context: Optional workflow context dictionary. |
| 218 | system_prompt: Optional custom system prompt (overrides default). |
| 219 | step_config: Optional step-specific configuration for tool filtering. |
| 220 | |
| 221 | Returns: |
| 222 | Tuple of (output, tokens) where output is the final response |
| 223 | and tokens is the total number of tokens used. |
| 224 | """ |
| 225 | if context is None: |
| 226 | context = {} |
| 227 | if system_prompt is not None: |
| 228 | system_prompt = resolve_system_prompt(system_prompt, context) |
| 229 | else: |
| 230 | system_prompt = get_yaml_system_prompt( |
| 231 | context.get("task_name", "unknown"), |
| 232 | context.get("goal", ""), |
| 233 | args, |
| 234 | context, |
| 235 | ) |
| 236 | |
| 237 | prompt = instruction |
| 238 | |
| 239 | messages = [ |
| 240 | {"role": "system", "content": system_prompt}, |
| 241 | {"role": "user", "content": prompt}, |
| 242 | ] |
| 243 | |
| 244 | tool_config = EffectiveToolConfig.compute(self.tools, context, step_config) |
| 245 | expose_submodules = context.get("expose_submodules_as_tools", True) |
| 246 | combined_tools = tool_config.tools + ( |
| 247 | tool_config.submodule_tools if expose_submodules else [] |
| 248 | ) |
| 249 | return self.multi_step_tool_call_loop( |
| 250 | step_id, |
| 251 | messages, |