Skip to content

Commit 195ec99

Browse files
committed
initial commit
1 parent 4ab004b commit 195ec99

File tree

4 files changed

+508
-0
lines changed

4 files changed

+508
-0
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# Order Return Processing System
2+
3+
An order return processing system built with Azure Functions and OpenAI Agents, demonstrating advanced orchestration patterns and multi-agent workflows.
4+
5+
## Overview
6+
7+
This system automatically processes customer return requests using AI agents to validate return reasons, process refunds, and route edge cases to human review. It showcases real-world business logic implementation with Azure Durable Functions.
8+
9+
## Quick Start
10+
11+
### Submit a Return Request
12+
```bash
13+
curl -X POST http://localhost:7071/api/order_return_processor \
14+
-H "Content-Type: application/json" \
15+
-d '{
16+
"order_id": "ORD-12345",
17+
"customer_id": "CUST-67890",
18+
"product_category": "Electronics",
19+
"purchase_date": "2024-10-01",
20+
"return_reason": "Product arrived damaged in shipping"
21+
}'
22+
```
23+
24+
### Check Processing Status
25+
```bash
26+
# Use the statusQueryGetUri from the submission response
27+
curl http://localhost:7071/runtime/webhooks/durabletask/instances/{instance_id}
28+
```
29+
30+
## API Reference
31+
32+
### Endpoints
33+
34+
| Method | Endpoint | Description |
35+
|--------|----------|-------------|
36+
| `POST` | `/api/order_return_processor` | Submit a new return request |
37+
| `GET` | `/runtime/webhooks/durabletask/instances/{instance_id}` | Check processing status |
38+
39+
40+
### Request Schema
41+
42+
```json
43+
{
44+
"order_id": "string (required)",
45+
"customer_id": "string (required)",
46+
"product_category": "string (required)",
47+
"purchase_date": "string (required)",
48+
"return_reason": "string (required)"
49+
}
50+
```
51+
52+
## Business Logic
53+
54+
### Validation Rules
55+
56+
**✅ Auto-Approved Returns**
57+
- Defective or broken products
58+
- Wrong item shipped
59+
- Damaged during shipping
60+
- Product not as described
61+
- Quality issues
62+
- Size/fit problems
63+
64+
**❌ Requires Human Review**
65+
- Changed mind without valid cause
66+
- Found item cheaper elsewhere
67+
- Buyer's remorse
68+
- Financial reasons
69+
- Vague complaints
70+
71+
## Example Responses
72+
73+
### Successful Auto-Approval
74+
```json
75+
{
76+
"status": "approved_and_processed",
77+
"validation": {
78+
"agent_response": "Return approved - product defect identified",
79+
"validation_result": { "is_valid": true }
80+
},
81+
"refund": {
82+
"refund_details": {
83+
"success": true,
84+
"refund_amount": 93.00,
85+
"transaction_id": "REF-ABC123",
86+
"processing_time": "3-5 business days"
87+
}
88+
},
89+
"message": "Return approved and refund processed successfully"
90+
}
91+
```
92+
93+
### Human Review Required
94+
```json
95+
{
96+
"status": "pending_human_review",
97+
"validation": {
98+
"agent_response": "Return requires manual review - unclear reason",
99+
"validation_result": { "is_valid": false }
100+
},
101+
"human_review": {
102+
"review_ticket_id": "REV-XYZ789",
103+
"estimated_review_time": "24-48 hours",
104+
"message": "Your return request has been escalated for human review"
105+
}
106+
}
107+
```
108+
109+
## Architecture
110+
111+
The system uses a multi-agent orchestration pattern:
112+
113+
1. **Order Return Processor** (Main Orchestrator) - Coordinates the entire workflow
114+
2. **Validation Agent** - Analyzes return reasons against business rules
115+
3. **Refund Agent** - Processes approved refunds automatically
116+
4. **Human Review Activity** - Creates support tickets for manual cases
117+
118+
## File Structure
119+
120+
```
121+
basic/
122+
├── order_return_validation.py # Validation agent
123+
└── refund_processing.py # Refund processing agent
124+
125+
order_return_orchestrators.py # Main orchestration logic
126+
test_order_return.py # Testing examples and utilities
127+
```
128+
129+
## Testing
130+
131+
```bash
132+
# Start the function app
133+
func start
134+
135+
# Test valid return (should auto-approve)
136+
curl -X POST http://localhost:7071/api/order_return_processor \
137+
-H "Content-Type: application/json" \
138+
-d '{"order_id":"TEST-001","customer_id":"CUST-001","product_category":"Electronics","purchase_date":"2024-10-01","return_reason":"arrived damaged"}'
139+
140+
# Test invalid return (should require human review)
141+
curl -X POST http://localhost:7071/api/order_return_processor \
142+
-H "Content-Type: application/json" \
143+
-d '{"order_id":"TEST-002","customer_id":"CUST-002","product_category":"Clothing","purchase_date":"2024-09-15","return_reason":"changed my mind"}'
144+
145+
# Check status using the response from above requests
146+
# Look for "statusQueryGetUri" in the response and use that URL
147+
curl {statusQueryGetUri_from_response}
148+
```
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Copyright (c) Microsoft Corporation. All rights reserved.
2+
# Licensed under the MIT License.
3+
from __future__ import annotations
4+
5+
from pydantic import BaseModel
6+
from typing import Literal
7+
8+
from agents import Agent, Runner, function_tool
9+
10+
11+
class ReturnValidationResult(BaseModel):
12+
is_valid: bool
13+
reason: str
14+
confidence_score: float # 0.0 to 1.0
15+
order_id: str
16+
17+
18+
class OrderReturnRequest(BaseModel):
19+
order_id: str
20+
return_reason: str
21+
purchase_date: str
22+
product_category: str
23+
customer_id: str
24+
25+
26+
@function_tool
27+
def validate_return_reason(return_request: OrderReturnRequest) -> ReturnValidationResult:
28+
"""
29+
Validate if an order return reason is legitimate based on company policy.
30+
Valid reasons include: defective product, wrong item received, damaged in shipping,
31+
not as described, quality issues, size/fit issues (for clothing).
32+
Invalid reasons include: changed mind after 30 days, buyer's remorse,
33+
found cheaper elsewhere, impulse purchase regret.
34+
"""
35+
36+
# Simulate policy validation logic
37+
valid_reasons = [
38+
"defective", "damaged", "wrong item", "not as described",
39+
"quality issues", "size issue", "fit issue", "broken",
40+
"missing parts", "expired"
41+
]
42+
43+
invalid_reasons = [
44+
"changed mind", "buyer's remorse", "found cheaper",
45+
"impulse purchase", "don't need", "financial reasons"
46+
]
47+
48+
reason_lower = return_request.return_reason.lower()
49+
50+
# Check for valid reasons
51+
is_valid = any(valid_reason in reason_lower for valid_reason in valid_reasons)
52+
53+
# Check for invalid reasons
54+
if any(invalid_reason in reason_lower for invalid_reason in invalid_reasons):
55+
is_valid = False
56+
57+
# Calculate confidence based on keyword matching
58+
confidence = 0.8 if is_valid else 0.7
59+
60+
validation_reason = (
61+
"Return reason matches company policy for valid returns" if is_valid
62+
else "Return reason does not meet company return policy criteria"
63+
)
64+
65+
return ReturnValidationResult(
66+
is_valid=is_valid,
67+
reason=validation_reason,
68+
confidence_score=confidence,
69+
order_id=return_request.order_id
70+
)
71+
72+
73+
def main(return_request_data: dict):
74+
"""Main function to run the order return validation agent"""
75+
76+
agent = Agent(
77+
name="Order Return Validation Specialist",
78+
instructions="""
79+
You are an expert order return validation specialist. Your job is to:
80+
1. Analyze customer return requests carefully
81+
2. Determine if the return reason is valid according to company policy
82+
3. Provide clear reasoning for your decision
83+
4. Be fair but firm in applying policy guidelines
84+
85+
Valid return reasons typically include:
86+
- Defective or broken products
87+
- Wrong item shipped
88+
- Damaged during shipping
89+
- Product not as described
90+
- Quality issues
91+
- Size/fit problems (for applicable items)
92+
93+
Invalid return reasons typically include:
94+
- Changed mind without valid cause
95+
- Found item cheaper elsewhere
96+
- Buyer's remorse
97+
- Financial hardship
98+
- General dissatisfaction without specific issue
99+
100+
Always use the validate_return_reason tool to check the policy compliance.
101+
Based on the tool result, clearly state if the return is VALID or INVALID.
102+
End your response with either "Return is VALID" or "Return is INVALID".
103+
""",
104+
tools=[validate_return_reason],
105+
)
106+
107+
# Convert dict to OrderReturnRequest
108+
return_request = OrderReturnRequest(**return_request_data)
109+
110+
user_message = f"""
111+
Please validate this return request:
112+
113+
Order ID: {return_request.order_id}
114+
Customer ID: {return_request.customer_id}
115+
Product Category: {return_request.product_category}
116+
Purchase Date: {return_request.purchase_date}
117+
Return Reason: {return_request.return_reason}
118+
119+
Is this a valid return request according to our company policy?
120+
"""
121+
122+
result = Runner.run_sync(agent, user_message)
123+
# Parse the agent's response to extract validation decision
124+
agent_response = result.final_output
125+
is_valid = "valid" in str(agent_response).lower() and "invalid" not in str(agent_response).lower()
126+
127+
# Create a structured validation result
128+
validation_result = {
129+
"is_valid": is_valid,
130+
"reason": "Parsed from agent response",
131+
"confidence_score": 0.8 if is_valid else 0.7,
132+
"order_id": return_request_data.get("order_id")
133+
}
134+
135+
return {
136+
"agent_response": agent_response,
137+
"validation_result": validation_result
138+
}

0 commit comments

Comments
 (0)