dexteredep commited on
Commit
13d610a
·
1 Parent(s): 0edaf65
Files changed (1) hide show
  1. orchestrator-agent/agent.py +67 -29
orchestrator-agent/agent.py CHANGED
@@ -98,52 +98,90 @@ Always structure your response with:
98
  self,
99
  agent_name: str,
100
  payload: Dict[str, Any],
101
- timeout: float = 120.0
 
102
  ) -> Dict[str, Any]:
103
  """
104
- Call an agent via HTTP (workaround for bl_agent DNS issues)
105
 
106
  Args:
107
  agent_name: Name of the agent (e.g., 'risk-assessment-agent')
108
  payload: Request payload
109
  timeout: Request timeout in seconds
 
110
 
111
  Returns:
112
  Agent response as dictionary
113
 
114
  Raises:
115
- Exception: If HTTP request fails
116
  """
117
  agent_url = f"{self.base_url}/{agent_name}"
118
 
119
- try:
120
- headers = {"Content-Type": "application/json"}
121
- if self.blaxel_api_key:
122
- headers["Authorization"] = f"Bearer {self.blaxel_api_key}"
123
-
124
- logger.info(f"Calling {agent_name} via HTTP at {agent_url}")
125
- self._update_progress(f"Calling {agent_name}...")
126
-
127
- async with httpx.AsyncClient(timeout=timeout) as client:
128
- response = await client.post(
129
- agent_url,
130
- json=payload,
131
- headers=headers
132
- )
133
- response.raise_for_status()
134
- result = response.json()
135
 
136
- self._update_progress(f"{agent_name} completed successfully")
137
- return result
 
138
 
139
- except httpx.TimeoutException:
140
- raise Exception(f"{agent_name} request timed out after {timeout}s")
141
- except httpx.HTTPStatusError as e:
142
- raise Exception(f"{agent_name} returned HTTP {e.response.status_code}: {e.response.text}")
143
- except httpx.HTTPError as e:
144
- raise Exception(f"{agent_name} HTTP error: {str(e)}")
145
- except Exception as e:
146
- raise Exception(f"{agent_name} call failed: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
  async def process_construction_plan(
149
  self,
 
98
  self,
99
  agent_name: str,
100
  payload: Dict[str, Any],
101
+ timeout: float = 120.0,
102
+ max_retries: int = 3
103
  ) -> Dict[str, Any]:
104
  """
105
+ Call an agent via HTTP with retry logic for empty responses
106
 
107
  Args:
108
  agent_name: Name of the agent (e.g., 'risk-assessment-agent')
109
  payload: Request payload
110
  timeout: Request timeout in seconds
111
+ max_retries: Maximum number of retry attempts (default: 3)
112
 
113
  Returns:
114
  Agent response as dictionary
115
 
116
  Raises:
117
+ Exception: If HTTP request fails after all retries
118
  """
119
  agent_url = f"{self.base_url}/{agent_name}"
120
 
121
+ for attempt in range(1, max_retries + 1):
122
+ try:
123
+ headers = {"Content-Type": "application/json"}
124
+ if self.blaxel_api_key:
125
+ headers["Authorization"] = f"Bearer {self.blaxel_api_key}"
 
 
 
 
 
 
 
 
 
 
 
126
 
127
+ attempt_msg = f" (attempt {attempt}/{max_retries})" if attempt > 1 else ""
128
+ logger.info(f"Calling {agent_name} via HTTP at {agent_url}{attempt_msg}")
129
+ self._update_progress(f"Calling {agent_name}...{attempt_msg}")
130
 
131
+ async with httpx.AsyncClient(timeout=timeout) as client:
132
+ response = await client.post(
133
+ agent_url,
134
+ json=payload,
135
+ headers=headers
136
+ )
137
+ response.raise_for_status()
138
+ result = response.json()
139
+
140
+ # Check for empty or invalid response
141
+ if not result or not isinstance(result, dict):
142
+ raise Exception(f"Empty or invalid response from {agent_name}")
143
+
144
+ # Check if response indicates success but has no data
145
+ if result.get('success') and not any(key in result for key in ['data', 'facility_data', 'recommendations', 'cost_data', 'image_base64']):
146
+ raise Exception(f"Empty data in successful response from {agent_name}")
147
+
148
+ self._update_progress(f"{agent_name} completed successfully")
149
+ return result
150
+
151
+ except httpx.TimeoutException as e:
152
+ error_msg = f"{agent_name} request timed out after {timeout}s"
153
+ if attempt < max_retries:
154
+ logger.warning(f"{error_msg}, retrying...")
155
+ await asyncio.sleep(2 * attempt) # Exponential backoff
156
+ continue
157
+ raise Exception(error_msg)
158
+
159
+ except httpx.HTTPStatusError as e:
160
+ error_msg = f"{agent_name} returned HTTP {e.response.status_code}: {e.response.text}"
161
+ if attempt < max_retries and e.response.status_code >= 500:
162
+ logger.warning(f"{error_msg}, retrying...")
163
+ await asyncio.sleep(2 * attempt)
164
+ continue
165
+ raise Exception(error_msg)
166
+
167
+ except httpx.HTTPError as e:
168
+ error_msg = f"{agent_name} HTTP error: {str(e)}"
169
+ if attempt < max_retries:
170
+ logger.warning(f"{error_msg}, retrying...")
171
+ await asyncio.sleep(2 * attempt)
172
+ continue
173
+ raise Exception(error_msg)
174
+
175
+ except Exception as e:
176
+ error_msg = f"{agent_name} call failed: {str(e)}"
177
+ if attempt < max_retries:
178
+ logger.warning(f"{error_msg}, retrying...")
179
+ await asyncio.sleep(2 * attempt)
180
+ continue
181
+ raise Exception(error_msg)
182
+
183
+ # Should never reach here, but just in case
184
+ raise Exception(f"{agent_name} failed after {max_retries} attempts")
185
 
186
  async def process_construction_plan(
187
  self,