Mixin providing basic step and task step execution. These are the most common step types, used for direct LLM interactions with optional tool usage and conversation history management. Required Attributes: llm_executor: LLMExecutor for running LLM completions. tools: Li
| 21 | |
| 22 | |
| 23 | class BasicStepsMixin: |
| 24 | """Mixin providing basic step and task step execution. |
| 25 | |
| 26 | These are the most common step types, used for direct LLM interactions |
| 27 | with optional tool usage and conversation history management. |
| 28 | |
| 29 | Required Attributes: |
| 30 | llm_executor: LLMExecutor for running LLM completions. |
| 31 | tools: List of available tool definitions. |
| 32 | """ |
| 33 | |
| 34 | def execute_basic_step( |
| 35 | self, |
| 36 | step_data: Dict[str, Any], |
| 37 | context: Dict[str, Any], |
| 38 | step_number: int, |
| 39 | args: EffectiveArgs, |
| 40 | logger: Logger, |
| 41 | ) -> Tuple[Any, int]: |
| 42 | """Execute a step with persistent conversation history. |
| 43 | |
| 44 | Steps maintain conversation history across iterations, enabling |
| 45 | multi-turn interactions with tool use. Each step appends a new |
| 46 | user message to the workflow-level conversation history and runs |
| 47 | the model against that shared history. |
| 48 | |
| 49 | Args: |
| 50 | step_data: Step configuration containing 'step' key with: |
| 51 | - instruction: The prompt to send to the LLM (required) |
| 52 | - name: Optional step name for logging |
| 53 | - system_prompt: Ignored (use workflow-level instead) |
| 54 | - save_as: Optional variable name to save output to context |
| 55 | context: Current workflow context dictionary. |
| 56 | step_number: Identifier for this step in the workflow. |
| 57 | args: Effective arguments for LLM configuration. |
| 58 | logger: Logger instance for output. |
| 59 | |
| 60 | Returns: |
| 61 | Tuple of (output, tokens) where output is the final LLM response |
| 62 | and tokens is the total number of tokens used across all iterations. |
| 63 | """ |
| 64 | step = step_data["step"] |
| 65 | raw_name = step.get("name", f"step_{step_number}") |
| 66 | name = expand_template_variables(raw_name, context) |
| 67 | instruction = step["instruction"] |
| 68 | expanded_instruction = expand_template_variables(instruction, context) |
| 69 | logger(f"\n==== Executing step {step_number}: {name} ====") |
| 70 | logger(f"Instruction: {expanded_instruction}") |
| 71 | |
| 72 | system_prompt = step.get("system_prompt") |
| 73 | history = ensure_conversation_history(context, args) |
| 74 | if system_prompt is not None: |
| 75 | logger( |
| 76 | "Step system_prompt is ignored; set system_prompt at the workflow level instead." |
| 77 | ) |
| 78 | |
| 79 | history.append({"role": "user", "content": expanded_instruction}) |
| 80 | working_messages = list(history) |
nothing calls this directly
no outgoing calls
no test coverage detected