Building an Order Tracking Agent: Real-Time Status Updates via AI
Build an AI agent that looks up order status in real time, formats tracking updates conversationally, sends proactive notifications, and integrates with shipping carrier APIs for end-to-end visibility.
Order Tracking Is the Most Common Support Query
Across e-commerce, "where is my order" accounts for 25-40% of all support contacts. It is also one of the easiest queries to automate — the information exists in structured databases and carrier APIs. An order tracking agent that reliably answers these questions eliminates the single largest category of support volume.
Defining the Order Lookup Tool
The agent needs a tool that queries your order database by order ID or customer email. Using the OpenAI Agents SDK tool pattern, we define this as a function the agent can call.
from dataclasses import dataclass
from datetime import datetime
from typing import Optional
from agents import function_tool
@dataclass
class OrderStatus:
order_id: str
status: str
items: list[dict]
shipping_carrier: Optional[str]
tracking_number: Optional[str]
estimated_delivery: Optional[str]
last_update: str
events: list[dict]
# Simulated database lookup
ORDER_DB = {
"ORD-12345": OrderStatus(
order_id="ORD-12345",
status="in_transit",
items=[
{"name": "Wireless Headphones", "qty": 1, "price": 79.99}
],
shipping_carrier="UPS",
tracking_number="1Z999AA10123456784",
estimated_delivery="2026-03-19",
last_update="2026-03-16T14:30:00Z",
events=[
{"time": "2026-03-14T10:00:00Z", "description": "Order placed"},
{"time": "2026-03-15T08:00:00Z", "description": "Shipped from warehouse"},
{"time": "2026-03-16T14:30:00Z", "description": "In transit - Chicago, IL"},
],
),
}
@function_tool
def lookup_order(order_id: str) -> str:
"""Look up order status by order ID."""
order = ORDER_DB.get(order_id.upper())
if not order:
return f"No order found with ID {order_id}"
return (
f"Order {order.order_id}: {order.status}\n"
f"Items: {', '.join(i['name'] for i in order.items)}\n"
f"Carrier: {order.shipping_carrier}\n"
f"Tracking: {order.tracking_number}\n"
f"Estimated delivery: {order.estimated_delivery}\n"
f"Last update: {order.events[-1]['description']} "
f"({order.events[-1]['time']})"
)
@function_tool
def lookup_orders_by_email(email: str) -> str:
"""Look up all orders for a customer email."""
# In production, query the database by customer email
matching = [
o for o in ORDER_DB.values()
# Simplified — real implementation queries by email
]
if not matching:
return f"No orders found for {email}"
return "\n---\n".join(
f"{o.order_id}: {o.status} (ETA: {o.estimated_delivery})"
for o in matching
)
Carrier API Integration
For real-time tracking beyond what your internal database stores, integrate directly with carrier APIs. This gives the agent up-to-the-minute location data.
import httpx
class CarrierTracker:
def __init__(self):
self.carriers = {
"UPS": "https://api.ups.com/track/v1",
"FedEx": "https://apis.fedex.com/track/v1",
"USPS": "https://api.usps.com/tracking/v3",
}
async def get_tracking(
self, carrier: str, tracking_number: str
) -> dict:
base_url = self.carriers.get(carrier)
if not base_url:
return {"error": f"Unsupported carrier: {carrier}"}
async with httpx.AsyncClient() as client:
response = await client.get(
f"{base_url}/shipments/{tracking_number}",
headers={"Authorization": "Bearer <token>"},
timeout=10.0,
)
if response.status_code == 200:
return response.json()
return {
"error": f"Tracking lookup failed: {response.status_code}"
}
def format_tracking_response(self, data: dict) -> str:
if "error" in data:
return data["error"]
events = data.get("events", [])
lines = []
for event in events[-5:]:
lines.append(
f" {event['timestamp']}: {event['description']} "
f"- {event.get('location', 'N/A')}"
)
return "\n".join(lines)
Building the Agent
The agent combines the lookup tools with instructions that tell it how to handle various order status scenarios.
See AI Voice Agents Handle Real Calls
Book a free demo or calculate how much you can save with AI voice automation.
from agents import Agent, Runner
order_agent = Agent(
name="Order Tracking Agent",
instructions="""You are an order tracking specialist. Help customers
check their order status.
When a customer asks about an order:
1. Ask for their order ID if not provided
2. Use lookup_order to get the status
3. Present the information clearly and conversationally
4. If the package is delayed, acknowledge the delay and provide
the updated estimate
5. If delivered, confirm delivery and ask if they received it
Never reveal internal system details. Format dates in a
human-friendly way (e.g., "Wednesday, March 19th").""",
tools=[lookup_order, lookup_orders_by_email],
)
async def handle_order_query(user_message: str) -> str:
result = await Runner.run(order_agent, user_message)
return result.final_output
Proactive Update Notifications
Beyond reactive lookups, a production order agent sends proactive updates when shipment status changes. This reduces inbound "where is my order" volume significantly.
from datetime import timedelta
class ProactiveNotifier:
def __init__(self, carrier_tracker: CarrierTracker):
self.tracker = carrier_tracker
self.notified_events: set[str] = set()
async def check_and_notify(self, order: OrderStatus) -> Optional[str]:
if not order.tracking_number or not order.shipping_carrier:
return None
data = await self.tracker.get_tracking(
order.shipping_carrier, order.tracking_number
)
if "error" in data:
return None
latest_event = data.get("events", [{}])[-1]
event_key = (
f"{order.order_id}:{latest_event.get('id', '')}"
)
if event_key in self.notified_events:
return None
self.notified_events.add(event_key)
status = latest_event.get("description", "Updated")
return (
f"Update on your order {order.order_id}: {status}. "
f"Estimated delivery: {order.estimated_delivery}."
)
FAQ
How do I authenticate the customer before showing order details?
Require the customer to verify their email or phone number associated with the order before returning any details. Never show order information based solely on an order ID, as these can be guessed or shared. Use a one-time code or session-based authentication for chat channels.
What if the carrier API is down or slow?
Always fall back to your internal database status when the carrier API is unavailable. Set a 5-second timeout on carrier requests and return the last known status with a note that live tracking is temporarily unavailable. Customers prefer a slightly stale answer over no answer.
How should the agent handle lost packages?
If the tracking shows "delivered" but the customer says they did not receive it, the agent should collect details (delivery date, address confirmation) and escalate to a human agent with authority to issue replacements or refunds. Lost package resolution typically requires judgment calls the AI should not make autonomously.
#OrderTracking #CustomerSupport #ToolUse #APIIntegration #AIAgents #AgenticAI #LearnAI #AIEngineering
CallSphere Team
Expert insights on AI voice agents and customer communication automation.
Try CallSphere AI Voice Agents
See how AI voice agents work for your industry. Live demo available -- no signup required.