Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions runner/arazzo_runner/executor/action_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ def __init__(self, source_descriptions: dict[str, Any]):
"""
self.source_descriptions = source_descriptions

def determine_next_action(self, step: dict, success: bool, state: ExecutionState) -> dict:
def determine_next_action(self, step: dict, success: bool, state: ExecutionState, response: dict | None = None) -> dict:
"""
Determine the next action based on step success/failure

Args:
step: Step definition
success: Whether the step succeeded
state: Current execution state
response: HTTP response from the step execution (used to evaluate $statusCode criteria)

Returns:
Dictionary with action type and parameters
Expand All @@ -59,7 +60,7 @@ def determine_next_action(self, step: dict, success: bool, state: ExecutionState
if "criteria" in action:
criteria = action.get("criteria", [])
logger.info(f"Action {action_name} has {len(criteria)} criteria")
criteria_met = self._check_action_criteria(criteria, state)
criteria_met = self._check_action_criteria(criteria, state, response)

if not criteria_met:
logger.info(f"Action {action_name} criteria not met, skipping")
Expand Down Expand Up @@ -99,7 +100,7 @@ def determine_next_action(self, step: dict, success: bool, state: ExecutionState
if "criteria" in action:
criteria = action.get("criteria", [])
logger.info(f"Failure action {action_name} has {len(criteria)} criteria")
criteria_met = self._check_action_criteria(criteria, state)
criteria_met = self._check_action_criteria(criteria, state, response)

if not criteria_met:
logger.info(f"Failure action {action_name} criteria not met, skipping")
Expand Down Expand Up @@ -151,21 +152,24 @@ def determine_next_action(self, step: dict, success: bool, state: ExecutionState
)
return {"type": ActionType.END}

def _check_action_criteria(self, criteria: list[dict], state: ExecutionState) -> bool:
def _check_action_criteria(self, criteria: list[dict], state: ExecutionState, response: dict | None = None) -> bool:
"""
Check if action criteria are met

Args:
criteria: List of criteria to check
state: Current execution state
response: HTTP response from the step execution (provides $statusCode and $response)

Returns:
True if all criteria are met, False otherwise
"""
logger.info(f"Checking {len(criteria)} action criteria")

# Context for evaluating criteria
context = {}
# Build evaluation context — populate statusCode and response from the step response
# so that conditions like "$statusCode == 200" and "$response.body#/..." resolve correctly.
status_code = response.get("status_code") if response else None
context = {"statusCode": status_code, "response": response} if response is not None else {}

Comment thread
HimethW marked this conversation as resolved.
# Check each criterion
for i, criterion in enumerate(criteria):
Expand All @@ -192,7 +196,7 @@ def _check_action_criteria(self, criteria: list[dict], state: ExecutionState) ->
# Check criterion based on type
if criterion_type == "simple":
result = ExpressionEvaluator.evaluate_simple_condition(
condition, state, self.source_descriptions, context
condition, state, self.source_descriptions, local_context
)
if not result:
logger.warning(f"Simple condition failed: {condition}")
Expand Down
10 changes: 8 additions & 2 deletions runner/arazzo_runner/executor/step_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,20 @@ def _execute_nested_workflow(self, step: dict, state: ExecutionState) -> dict:
"""
raise NotImplementedError("Nested workflow execution is handled by the runner")

def determine_next_action(self, step: dict, success: bool, state: ExecutionState) -> dict:
def determine_next_action(self, step: dict, success: bool, state: ExecutionState, response: dict | None = None) -> dict:
"""
Determine the next action based on step success/failure

Args:
step: Step definition
success: Whether the step succeeded
state: Current execution state
response: HTTP response from the step execution (used to evaluate $statusCode and $response criteria)

Returns:
action: Dictionary with action type and parameters
"""
return self.action_handler.determine_next_action(step, success, state)
return self.action_handler.determine_next_action(step, success, state, response)

def execute_operation(
self,
Expand Down
4 changes: 3 additions & 1 deletion runner/arazzo_runner/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,9 @@ def execute_next_step(self, execution_id: str) -> dict[str, Any]:
state.workflow_outputs[output_name] = value

# Determine next action
next_action = self.step_executor.determine_next_action(next_step, success, state)
next_action = self.step_executor.determine_next_action(
next_step, success, state, step_result.get("response")
)
Comment thread
HimethW marked this conversation as resolved.

# Trigger step_complete event
self._trigger_event(
Expand Down