mashrur950 commited on
Commit
ac8bca0
Β·
1 Parent(s): b7ebcf3

enhance iterative agentic loop and optimize configuration settings

Browse files
Files changed (2) hide show
  1. agent.py +171 -82
  2. config.py +84 -47
agent.py CHANGED
@@ -2,6 +2,8 @@
2
  FleetMind AI Agent
3
  Autonomous fleet management agent using Gemini 2.0 Flash
4
  Track 2: MCP in Action - Enterprise Category
 
 
5
  """
6
 
7
  import json
@@ -44,6 +46,7 @@ class FleetMindAgent:
44
  Uses Gemini 2.0 Flash for reasoning and MCP tools for execution
45
 
46
  Advanced Features:
 
47
  - Context Engineering: Smart conversation memory with summarization
48
  - Multi-step Planning: Complex task breakdown and execution
49
  - Reasoning Transparency: Detailed explanation of decision-making
@@ -60,12 +63,12 @@ class FleetMindAgent:
60
  self.task_context: dict = {} # Current task context
61
  self.max_history_length = 20 # Max messages before summarization
62
 
63
- # Initialize Gemini
64
  genai.configure(api_key=gemini_api_key)
65
  self.model = genai.GenerativeModel(
66
  model_name=Config.GEMINI_MODEL,
67
  generation_config={
68
- "temperature": Config.AGENT_TEMPERATURE,
69
  "top_p": 0.95,
70
  "top_k": 40,
71
  "max_output_tokens": 8192,
@@ -149,17 +152,17 @@ Provide a concise summary in 3-4 sentences."""
149
 
150
  return "\n\n".join(schema_parts)
151
 
152
- def _create_prompt(self, user_message: str) -> str:
153
  """
154
- Create the full prompt for the AI model with Context Engineering
155
- Includes conversation summary, user preferences, and task context
156
  """
157
  # Get current date/time for context
158
  now = datetime.now()
159
  current_time = now.strftime("%Y-%m-%d %H:%M:%S")
160
  default_delivery_time = (now + timedelta(hours=2)).strftime("%Y-%m-%dT%H:%M:%S")
161
 
162
- # Build context with Context Engineering enhancements
163
  context = f"""
164
  Current Date/Time: {current_time}
165
  Default Expected Delivery Time (if not specified): {default_delivery_time}
@@ -168,11 +171,11 @@ Connected to MCP Server: {self.mcp_client.is_connected}
168
  Available Tools: {len(self.mcp_client.tools)}
169
  """
170
 
171
- # Add conversation summary if available (Context Engineering)
172
  if self.context_summary:
173
  context += f"\n**Conversation Summary**: {self.context_summary}\n"
174
 
175
- # Add learned user preferences (Context Engineering)
176
  if self.user_preferences:
177
  prefs_text = "\n**Learned User Preferences**:\n"
178
  if self.user_preferences.get("prefers_urgent"):
@@ -181,8 +184,8 @@ Available Tools: {len(self.mcp_client.tools)}
181
  prefs_text += "- User frequently handles fragile items\n"
182
  context += prefs_text
183
 
184
- # Recent conversation context (limited to prevent overflow)
185
- recent_history = self.conversation_history[-6:] if self.conversation_history else []
186
  history_text = ""
187
  if recent_history:
188
  history_text = "\n\n**Recent Conversation**:\n"
@@ -194,39 +197,83 @@ Available Tools: {len(self.mcp_client.tools)}
194
  # Tool schema
195
  tools_schema = self._build_tools_schema()
196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  return f"""{AGENT_SYSTEM_PROMPT}
198
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  ## Context
200
  {context}
201
  {history_text}
202
 
203
  ## Available Tools Schema
204
  {tools_schema}
 
205
 
206
- ## User Request
207
  {user_message}
208
 
209
- ## Your Response Format
210
- Respond with a JSON object containing:
211
- {{
212
- "reasoning": "Your step-by-step thinking process (be detailed and explain WHY you choose certain actions)",
213
- "plan": [
214
- {{
215
- "step": 1,
216
- "action": "Description of what you're doing",
217
- "tool": "tool_name or null if no tool needed",
218
- "arguments": {{}} // tool arguments if applicable
219
- }}
220
- ],
221
- "final_message": "Your response to the user after executing the plan"
222
- }}
223
-
224
- If no tools are needed (e.g., answering a question), set plan to an empty array.
225
- IMPORTANT: Only include the JSON object in your response, no other text.
226
  """
227
 
228
- def _parse_ai_response(self, response_text: str) -> dict:
229
- """Parse the AI's JSON response"""
230
  # Try to extract JSON from the response
231
  try:
232
  # First try direct parse
@@ -250,21 +297,21 @@ IMPORTANT: Only include the JSON object in your response, no other text.
250
  except json.JSONDecodeError:
251
  pass
252
 
253
- # Fallback: return as simple message
254
  return {
255
- "reasoning": "Direct response",
256
- "plan": [],
257
- "final_message": response_text
 
258
  }
259
 
260
  async def process_message(self, user_message: str) -> AgentResponse:
261
  """
262
- Process a user message and return the agent's response
263
 
264
- Context Engineering Applied:
265
- - Summarizes long conversations to prevent context overflow
266
- - Learns and applies user preferences
267
- - Maintains task context across messages
268
 
269
  Args:
270
  user_message: The user's natural language input
@@ -282,57 +329,99 @@ IMPORTANT: Only include the JSON object in your response, no other text.
282
  "content": user_message
283
  })
284
 
285
- # Generate AI response
286
- prompt = self._create_prompt(user_message)
287
-
288
- try:
289
- response = self.model.generate_content(prompt)
290
- ai_response_text = response.text
291
- except Exception as e:
292
- return AgentResponse(
293
- message=f"Error generating AI response: {str(e)}",
294
- success=False,
295
- error=str(e)
296
- )
297
-
298
- # Parse the response
299
- parsed = self._parse_ai_response(ai_response_text)
300
- reasoning = parsed.get("reasoning", "")
301
- plan = parsed.get("plan", [])
302
- final_message = parsed.get("final_message", "")
303
-
304
- # Execute the plan
305
  steps: list[AgentStep] = []
306
  tools_called: list[str] = []
 
 
307
 
308
- for i, step_plan in enumerate(plan[:self.max_tool_calls]):
309
- step = AgentStep(
310
- step_number=i + 1,
311
- action=step_plan.get("action", ""),
312
- tool_name=step_plan.get("tool"),
313
- tool_args=step_plan.get("arguments", {}),
314
- reasoning=step_plan.get("reasoning", "")
315
- )
316
 
317
- # Execute tool if specified
318
- if step.tool_name:
319
- tool_result = await self.mcp_client.call_tool(
320
- step.tool_name,
321
- step.tool_args
322
- )
323
- step.result = tool_result.result if tool_result.success else tool_result.error
324
- tools_called.append(step.tool_name)
325
 
326
- # If tool failed, note it
327
- if not tool_result.success:
328
- step.action += f" (FAILED: {tool_result.error})"
329
 
330
- steps.append(step)
 
 
 
 
 
 
 
 
 
331
 
332
- # If we executed tools, regenerate final message with results
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
333
  if steps:
334
  final_message = await self._generate_final_response(
335
- user_message, steps, reasoning
336
  )
337
 
338
  # Add assistant response to history
@@ -347,7 +436,7 @@ IMPORTANT: Only include the JSON object in your response, no other text.
347
  return AgentResponse(
348
  message=final_message,
349
  steps=steps,
350
- reasoning=reasoning,
351
  tools_called=tools_called,
352
  success=True
353
  )
 
2
  FleetMind AI Agent
3
  Autonomous fleet management agent using Gemini 2.0 Flash
4
  Track 2: MCP in Action - Enterprise Category
5
+
6
+ FIXED: True iterative agentic loop - Gemini sees tool results and decides next action
7
  """
8
 
9
  import json
 
46
  Uses Gemini 2.0 Flash for reasoning and MCP tools for execution
47
 
48
  Advanced Features:
49
+ - TRUE ITERATIVE AGENTIC LOOP: Model sees each tool result before deciding next action
50
  - Context Engineering: Smart conversation memory with summarization
51
  - Multi-step Planning: Complex task breakdown and execution
52
  - Reasoning Transparency: Detailed explanation of decision-making
 
63
  self.task_context: dict = {} # Current task context
64
  self.max_history_length = 20 # Max messages before summarization
65
 
66
+ # Initialize Gemini - CRITICAL: temperature=1.0 for Gemini 2.0 reasoning
67
  genai.configure(api_key=gemini_api_key)
68
  self.model = genai.GenerativeModel(
69
  model_name=Config.GEMINI_MODEL,
70
  generation_config={
71
+ "temperature": 1.0, # IMPORTANT: Gemini 2.0 reasoning optimized for 1.0
72
  "top_p": 0.95,
73
  "top_k": 40,
74
  "max_output_tokens": 8192,
 
152
 
153
  return "\n\n".join(schema_parts)
154
 
155
+ def _create_iterative_prompt(self, user_message: str, execution_context: list[dict]) -> str:
156
  """
157
+ Create prompt for iterative agentic loop.
158
+ Includes previous tool results so model can make informed decisions.
159
  """
160
  # Get current date/time for context
161
  now = datetime.now()
162
  current_time = now.strftime("%Y-%m-%d %H:%M:%S")
163
  default_delivery_time = (now + timedelta(hours=2)).strftime("%Y-%m-%dT%H:%M:%S")
164
 
165
+ # Build context
166
  context = f"""
167
  Current Date/Time: {current_time}
168
  Default Expected Delivery Time (if not specified): {default_delivery_time}
 
171
  Available Tools: {len(self.mcp_client.tools)}
172
  """
173
 
174
+ # Add conversation summary if available
175
  if self.context_summary:
176
  context += f"\n**Conversation Summary**: {self.context_summary}\n"
177
 
178
+ # Add learned user preferences
179
  if self.user_preferences:
180
  prefs_text = "\n**Learned User Preferences**:\n"
181
  if self.user_preferences.get("prefers_urgent"):
 
184
  prefs_text += "- User frequently handles fragile items\n"
185
  context += prefs_text
186
 
187
+ # Recent conversation history
188
+ recent_history = self.conversation_history[-4:] if self.conversation_history else []
189
  history_text = ""
190
  if recent_history:
191
  history_text = "\n\n**Recent Conversation**:\n"
 
197
  # Tool schema
198
  tools_schema = self._build_tools_schema()
199
 
200
+ # Build execution context string showing what's been done
201
+ execution_history = ""
202
+ if execution_context:
203
+ execution_history = "\n\n## EXECUTION HISTORY (What you've done so far)\n"
204
+ for step in execution_context:
205
+ step_num = step.get("step", "?")
206
+ tool_name = step.get("tool", "N/A")
207
+ args = step.get("arguments", {})
208
+ result = step.get("result", "N/A")
209
+ execution_history += f"""
210
+ ### Step {step_num}: Called {tool_name}
211
+ Arguments: {json.dumps(args, indent=2)}
212
+ Result: {json.dumps(result, indent=2) if isinstance(result, dict) else result}
213
+ """
214
+
215
  return f"""{AGENT_SYSTEM_PROMPT}
216
 
217
+ ═══════════════════════════════════════════════════════════════
218
+ ⚑ CRITICAL: ITERATIVE AGENTIC REASONING
219
+ ═══════════════════════════════════════════════════════════════
220
+
221
+ You are in an ITERATIVE LOOP. Each turn, you can call ONE tool or finish.
222
+ After each tool call, you will see the result and decide the NEXT step.
223
+
224
+ **WORKFLOW:**
225
+ 1. Analyze what the user wants
226
+ 2. Determine the NEXT SINGLE action needed
227
+ 3. Either call a tool OR provide final response
228
+
229
+ **RESPONSE FORMAT (STRICT JSON):**
230
+
231
+ If you need to call a tool:
232
+ ```json
233
+ {{
234
+ "thinking": "My reasoning about what to do next...",
235
+ "action": "call_tool",
236
+ "tool": "tool_name",
237
+ "arguments": {{}},
238
+ "status": "in_progress"
239
+ }}
240
+ ```
241
+
242
+ If you're DONE (all steps complete):
243
+ ```json
244
+ {{
245
+ "thinking": "Summarizing what was accomplished...",
246
+ "action": "respond",
247
+ "message": "Your final response to the user",
248
+ "status": "complete"
249
+ }}
250
+ ```
251
+
252
+ **IMPORTANT RULES:**
253
+ 1. Call ONE tool at a time - you'll see the result before deciding next step
254
+ 2. USE ACTUAL DATA from previous tool results (coordinates, IDs, etc.)
255
+ 3. Don't guess values - use what the tools returned
256
+ 4. After geocoding, USE the lat/lng from the result in subsequent calls
257
+ 5. After creating order, USE the order_id for assignment
258
+
259
+ ═══════════════════════════════════════════════════════════════
260
+
261
  ## Context
262
  {context}
263
  {history_text}
264
 
265
  ## Available Tools Schema
266
  {tools_schema}
267
+ {execution_history}
268
 
269
+ ## Current User Request
270
  {user_message}
271
 
272
+ ## Your Next Action (JSON only, no other text)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
  """
274
 
275
+ def _parse_iterative_response(self, response_text: str) -> dict:
276
+ """Parse the AI's JSON response for iterative loop"""
277
  # Try to extract JSON from the response
278
  try:
279
  # First try direct parse
 
297
  except json.JSONDecodeError:
298
  pass
299
 
300
+ # Fallback: treat as final response
301
  return {
302
+ "thinking": "Direct response",
303
+ "action": "respond",
304
+ "message": response_text,
305
+ "status": "complete"
306
  }
307
 
308
  async def process_message(self, user_message: str) -> AgentResponse:
309
  """
310
+ Process a user message using TRUE ITERATIVE AGENTIC LOOP.
311
 
312
+ The model calls ONE tool at a time, sees the result, then decides
313
+ the next action. This allows proper use of tool results (like coordinates
314
+ from geocoding) in subsequent calls (like create_order).
 
315
 
316
  Args:
317
  user_message: The user's natural language input
 
329
  "content": user_message
330
  })
331
 
332
+ # Initialize execution tracking
333
+ execution_context: list[dict] = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
  steps: list[AgentStep] = []
335
  tools_called: list[str] = []
336
+ all_reasoning: list[str] = []
337
+ final_message = ""
338
 
339
+ # ITERATIVE AGENTIC LOOP
340
+ max_iterations = self.max_tool_calls + 2 # Allow extra iterations for reasoning
341
+ iteration = 0
 
 
 
 
 
342
 
343
+ while iteration < max_iterations:
344
+ iteration += 1
345
+ print(f"\nπŸ”„ Agent Iteration {iteration}/{max_iterations}")
 
 
 
 
 
346
 
347
+ # Generate next action
348
+ prompt = self._create_iterative_prompt(user_message, execution_context)
 
349
 
350
+ try:
351
+ response = self.model.generate_content(prompt)
352
+ ai_response_text = response.text
353
+ print(f"πŸ“ AI Response: {ai_response_text[:500]}...")
354
+ except Exception as e:
355
+ return AgentResponse(
356
+ message=f"Error generating AI response: {str(e)}",
357
+ success=False,
358
+ error=str(e)
359
+ )
360
 
361
+ # Parse the response
362
+ parsed = self._parse_iterative_response(ai_response_text)
363
+ thinking = parsed.get("thinking", "")
364
+ action = parsed.get("action", "respond")
365
+ status = parsed.get("status", "complete")
366
+
367
+ all_reasoning.append(f"Step {iteration}: {thinking}")
368
+
369
+ # Check if agent wants to call a tool
370
+ if action == "call_tool" and status != "complete":
371
+ tool_name = parsed.get("tool")
372
+ tool_args = parsed.get("arguments", {})
373
+
374
+ if not tool_name:
375
+ print("⚠️ No tool specified, treating as complete")
376
+ final_message = parsed.get("message", thinking)
377
+ break
378
+
379
+ print(f"πŸ”§ Calling tool: {tool_name}")
380
+ print(f" Args: {json.dumps(tool_args, indent=2)}")
381
+
382
+ # Execute the tool
383
+ tool_result = await self.mcp_client.call_tool(tool_name, tool_args)
384
+
385
+ result_data = tool_result.result if tool_result.success else {"error": tool_result.error}
386
+ print(f" Result: {json.dumps(result_data, indent=2) if isinstance(result_data, dict) else result_data}")
387
+
388
+ # Record the step
389
+ step = AgentStep(
390
+ step_number=len(steps) + 1,
391
+ action=thinking,
392
+ tool_name=tool_name,
393
+ tool_args=tool_args,
394
+ result=result_data,
395
+ reasoning=thinking
396
+ )
397
+ steps.append(step)
398
+ tools_called.append(tool_name)
399
+
400
+ # Add to execution context for next iteration
401
+ execution_context.append({
402
+ "step": len(execution_context) + 1,
403
+ "tool": tool_name,
404
+ "arguments": tool_args,
405
+ "result": result_data,
406
+ "success": tool_result.success
407
+ })
408
+
409
+ # Continue the loop - model will see this result next iteration
410
+
411
+ else:
412
+ # Agent is done - extract final message
413
+ final_message = parsed.get("message", thinking)
414
+ print(f"βœ… Agent complete: {final_message[:200]}...")
415
+ break
416
+
417
+ # If we hit max iterations without completing
418
+ if not final_message:
419
+ final_message = "I completed several operations. Please check the results above."
420
+
421
+ # Generate a nicely formatted final response if we have steps
422
  if steps:
423
  final_message = await self._generate_final_response(
424
+ user_message, steps, "\n".join(all_reasoning)
425
  )
426
 
427
  # Add assistant response to history
 
436
  return AgentResponse(
437
  message=final_message,
438
  steps=steps,
439
+ reasoning="\n".join(all_reasoning),
440
  tools_called=tools_called,
441
  success=True
442
  )
config.py CHANGED
@@ -22,8 +22,8 @@ class Config:
22
  GEMINI_MODEL: str = os.getenv("GEMINI_MODEL", "gemini-2.0-flash-exp")
23
 
24
  # Agent Configuration
25
- MAX_TOOL_CALLS_PER_TURN: int = int(os.getenv("MAX_TOOL_CALLS_PER_TURN", "5"))
26
- AGENT_TEMPERATURE: float = float(os.getenv("AGENT_TEMPERATURE", "0.7"))
27
 
28
  # UI Configuration
29
  APP_TITLE: str = "FleetMind AI Agent"
@@ -189,53 +189,90 @@ TOOL_DESCRIPTIONS = """
189
  """
190
 
191
  # System prompt for the AI agent
192
- AGENT_SYSTEM_PROMPT = f"""You are FleetMind AI Agent, an autonomous enterprise fleet management assistant.
193
 
194
- Your role is to help users manage their delivery fleet through natural language commands. You have access to 29 MCP tools for:
195
- - Creating and managing delivery orders
196
- - Managing drivers and their assignments
197
- - Intelligent route planning with traffic and weather awareness
198
- - AI-powered driver assignment optimization
199
 
200
- {TOOL_DESCRIPTIONS}
201
-
202
- ## How to Respond
203
-
204
- 1. **Understand Intent**: Parse the user's natural language request to understand what they want to accomplish.
205
-
206
- 2. **Plan Steps**: If the task requires multiple operations, plan the sequence of tool calls needed.
207
-
208
- 3. **Execute Tools**: Call the appropriate MCP tools with correct parameters.
209
-
210
- 4. **Explain Reasoning**: Always explain your reasoning process - what you're doing and why.
211
 
212
- 5. **Report Results**: Present results in a clear, human-readable format.
213
-
214
- ## Important Guidelines
215
-
216
- - Always geocode addresses before creating orders (to get lat/lng coordinates)
217
- - When creating orders, expected_delivery_time is MANDATORY (use ISO format: YYYY-MM-DDTHH:MM:SS)
218
- - For intelligent assignment, explain the AI's reasoning and confidence score
219
- - If a tool call fails, explain the error and suggest alternatives
220
- - Be proactive - offer relevant follow-up actions
221
-
222
- ## Example Interactions
223
-
224
- User: "Create an urgent order for John at 123 Main St, due by 5pm"
225
- You should:
226
- 1. Geocode "123 Main St" to get coordinates
227
- 2. Create order with priority=urgent, expected_delivery_time set to 5pm today
228
- 3. Report success and offer to assign a driver
229
-
230
- User: "Create a driver named Alex at Downtown SF with a van"
231
- You should:
232
- 1. Geocode "Downtown SF" to get coordinates (lat/lng)
233
- 2. Create driver with: name="Alex", vehicle_type="van", current_address="Downtown SF", current_lat=<from geocode>, current_lng=<from geocode>
234
- 3. Report success with driver details
235
 
236
- User: "Find the best driver for order ORD-xxx"
237
- You should:
238
- 1. Use intelligent_assign_order to leverage AI assignment
239
- 2. Explain the AI's reasoning and confidence
240
- 3. Confirm the assignment was created
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  """
 
22
  GEMINI_MODEL: str = os.getenv("GEMINI_MODEL", "gemini-2.0-flash-exp")
23
 
24
  # Agent Configuration
25
+ MAX_TOOL_CALLS_PER_TURN: int = int(os.getenv("MAX_TOOL_CALLS_PER_TURN", "10")) # Increased for multi-step workflows
26
+ AGENT_TEMPERATURE: float = float(os.getenv("AGENT_TEMPERATURE", "1.0")) # Gemini 2.0 optimized for 1.0
27
 
28
  # UI Configuration
29
  APP_TITLE: str = "FleetMind AI Agent"
 
189
  """
190
 
191
  # System prompt for the AI agent
192
+ AGENT_SYSTEM_PROMPT = f"""You are FleetMind AI Agent, an AUTONOMOUS enterprise fleet management assistant.
193
 
194
+ ═══════════════════════════════════════════════════════════════
195
+ 🎯 YOUR CORE MISSION
196
+ ═══════════════════════════════════════════════════════════════
 
 
197
 
198
+ You AUTONOMOUSLY manage delivery operations by executing multi-step workflows:
199
+ - Creating orders (geocode β†’ create β†’ assign)
200
+ - Managing drivers and assignments
201
+ - Intelligent route planning
202
+ - AI-powered driver optimization
 
 
 
 
 
 
203
 
204
+ {TOOL_DESCRIPTIONS}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
 
206
+ ═══════════════════════════════════════════════════════════════
207
+ ⚑ CRITICAL: MULTI-STEP EXECUTION RULES
208
+ ═══════════════════════════════════════════════════════════════
209
+
210
+ **RULE 1: DEPENDENCIES MATTER**
211
+ Many tasks require SEQUENTIAL tool calls where later calls depend on earlier results:
212
+ - geocode_address β†’ THEN create_order (using lat/lng from geocode)
213
+ - create_order β†’ THEN intelligent_assign_order (using order_id)
214
+ - geocode_address β†’ THEN create_driver (using lat/lng from geocode)
215
+
216
+ **RULE 2: USE ACTUAL DATA FROM TOOL RESULTS**
217
+ NEVER guess or fabricate values. ALWAYS use real data returned by tools:
218
+ - βœ… CORRECT: After geocode returns lat=37.7749, lng=-122.4194, use THOSE EXACT values
219
+ - ❌ WRONG: Making up coordinates like lat=0, lng=0 or placeholders
220
+
221
+ **RULE 3: COMPLETE THE FULL WORKFLOW**
222
+ When user says "create order and assign driver":
223
+ 1. First: geocode_address to get coordinates
224
+ 2. Then: create_order using those coordinates β†’ get order_id
225
+ 3. Then: intelligent_assign_order using that order_id
226
+ 4. Finally: Report complete results
227
+
228
+ **RULE 4: REQUIRED FIELDS FOR ORDERS**
229
+ - customer_name (string)
230
+ - delivery_address (string)
231
+ - delivery_lat (float) - FROM GEOCODING
232
+ - delivery_lng (float) - FROM GEOCODING
233
+ - expected_delivery_time (ISO 8601: YYYY-MM-DDTHH:MM:SS)
234
+
235
+ ═══════════════════════════════════════════════════════════════
236
+ πŸ“‹ EXAMPLE: COMPLETE ORDER CREATION WORKFLOW
237
+ ═══════════════════════════════════════════════════════════════
238
+
239
+ User: "Create urgent order for Sarah at 456 Oak Ave SF, assign best driver"
240
+
241
+ **Step 1 - Geocode:**
242
+ Tool: geocode_address
243
+ Args: {{"address": "456 Oak Ave, San Francisco, CA"}}
244
+ Result: {{"latitude": 37.7749, "longitude": -122.4194, ...}}
245
+
246
+ **Step 2 - Create Order (using geocode results):**
247
+ Tool: create_order
248
+ Args: {{
249
+ "customer_name": "Sarah",
250
+ "delivery_address": "456 Oak Ave, San Francisco, CA",
251
+ "delivery_lat": 37.7749, ← FROM STEP 1
252
+ "delivery_lng": -122.4194, ← FROM STEP 1
253
+ "expected_delivery_time": "2024-01-15T17:00:00",
254
+ "priority": "urgent"
255
+ }}
256
+ Result: {{"order_id": "ORD-abc123", ...}}
257
+
258
+ **Step 3 - Assign Driver (using order_id):**
259
+ Tool: intelligent_assign_order
260
+ Args: {{"order_id": "ORD-abc123"}} ← FROM STEP 2
261
+ Result: {{"assignment_id": "...", "driver": "...", ...}}
262
+
263
+ **Step 4 - Report to User:**
264
+ "Created urgent order ORD-abc123 for Sarah and assigned driver John (ETA 25 min)."
265
+
266
+ ═══════════════════════════════════════════════════════════════
267
+ ⚠️ IMPORTANT GUIDELINES
268
+ ═══════════════════════════════════════════════════════════════
269
+
270
+ 1. ALWAYS geocode addresses BEFORE creating orders/drivers
271
+ 2. expected_delivery_time is MANDATORY (ISO 8601 format)
272
+ 3. For intelligent assignment, include AI reasoning in response
273
+ 4. If a tool fails, explain error and suggest alternatives
274
+ 5. Be proactive - offer relevant follow-up actions
275
+ 6. When listing data, format as readable tables
276
+
277
+ ═══════════════════════════════════════════════════════════════
278
  """