By Sagar Shankaran, Founder of CallSphere
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.
Key takeaways
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.
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.
flowchart TD
USER(["User message"])
LLM["LLM call<br/>with tools schema"]
DECIDE{"Model wants<br/>to call a tool?"}
EXEC["Execute tool<br/>sandboxed runtime"]
RESULT["Append tool_result<br/>to messages"]
GUARD{"Output passes<br/>guardrails?"}
DONE(["Final reply"])
BLOCK(["Refuse and log"])
USER --> LLM --> DECIDE
DECIDE -->|Yes| EXEC --> RESULT --> LLM
DECIDE -->|No| GUARD
GUARD -->|Yes| DONE
GUARD -->|No| BLOCK
style LLM fill:#4f46e5,stroke:#4338ca,color:#fff
style EXEC fill:#ede9fe,stroke:#7c3aed,color:#1e1b4b
style GUARD fill:#f59e0b,stroke:#d97706,color:#1f2937
style DONE fill:#059669,stroke:#047857,color:#fff
style BLOCK fill:#dc2626,stroke:#b91c1c,color:#fff
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
)
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.
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
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)
The agent combines the lookup tools with instructions that tell it how to handle various order status scenarios.
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
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}."
)
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.
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
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.
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

Written by
Sagar Shankaran· Founder, CallSphere
LinkedInSagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
Ukrainian online stores use CallSphere AI voice and chat agents to answer order, delivery and returns questions 24/7 in Ukrainian and Russian, recover abandoned carts and scale support without hiring.
Orange Money and MTN MoMo agents in Liberia field endless customer questions and support calls. See how CallSphere AI voice and chat agents answer 24/7 in English, cut support pressure, and capture leads from about $50 a month.
A founder's guide to the personal AI assistant market: best AI assistant apps, business-grade options, and how CallSphere's voice agent fits in.
A founder's guide to free AI agents, low-code AI agent builders, and how to know when you should pay for a real platform like CallSphere.
Graphiti is the open-source temporal knowledge graph for AI agents in 2026. Learn how bi-temporal memory beats vector RAG for voice agents and long-running LLMs.
Chatbot app vs ChatGPT in 2026: a founder's clear take on the difference, when to use which, and how a real AI chatbot app development works.
© 2026 CallSphere Inc. All rights reserved.
Made within San Francisco