The voice agent that actually knows where your package is.
You know the drill. You call customer support, wait 10 minutes on hold, finally get through, and then... "Could you hold while I check that?" π€
Captain Cargo is different. Pick up the phone, ask "Where's my stuff?", and get an answer in milliseconds. No hold music. No sighing. Just your package status.
Built with FastAPI + Vapi + Sanity.io. Tested with 75 tests. Deployed and ready to go.
Imagine this:
You: "Hey, where's my package?"
Captain Cargo: "Your package TRK123456789 is on its way! Expected delivery: tomorrow by 5 PM."
You: "Thanks!"
Captain Cargo: "You're welcome! π"
That's it. That's the whole interaction. No menus, no "press 1 for...", no "your call is important to us."
| Feature | What It Means For You |
|---|---|
| π€ Conversational | Talk like a human, get human answers |
| π‘οΈ Bulletproof | Circuit breaker, retries, cache β won't crash when your database sneezes |
| π Observable | Health checks, metrics, logs β know what's happening |
| πͺ Hallucination-Safe | Only tells you what the database actually says |
| π§ͺ Tested | 75 tests. Every. Single. One. Passes. |
git clone https://github.com/Koushik0901/Captain-Cargo---AI-Delivery-Tracking-System.git
cd Captain-Cargo---AI-Delivery-Tracking-System
pip install -r requirements.txt
cp .env.example .env # Fill in your Sanity credentials# For development (auto-reload on changes)
uvicorn server:app --reload
# For production
python server.pyYour webhook will be live at http://127.0.0.1:8000/webhook π
Captain Cargo needs to know where your data lives. Here's the deal:
| Variable | What It Is | Default | Required? |
|---|---|---|---|
SANITY_PROJECT_ID |
Your Sanity project ID | β | β Yes |
SANITY_DATASET |
Which dataset to query | production |
β |
SANITY_API_TOKEN |
Read-only API token | β | β Yes |
CACHE_TTL |
How long to cache results (seconds) | 60 |
β |
LOG_LEVEL |
DEBUG, INFO, WARNING, ERROR | INFO |
β |
Drop these in your .env file and you're golden.
# Kubernetes liveness probe
curl http://localhost:8000/healthz
# β {"status":"ok"}
# Readiness (includes dependency status)
curl http://localhost:8000/readyz
# β {"status":"ready","dependencies":{"circuit_breaker":"closed","failure_count":0}}
# Metrics for monitoring
curl http://localhost:8000/metrics
# β {"requests_total":100,"cache_hits_total":60,"cache_hit_rate":0.6,...}POST /webhook
{
"message": {
"content": "Where's my package ABC123?",
"toolCalls": [
{
"function": {
"name": "track_delivery",
"arguments": "{\"trackingId\": \"ABC123\"}"
}
}
]
}
}Response:
{
"status": "success",
"message": "Your package ABC123 is in transit.",
"delivery_details": {
"tracking_number": "ABC123",
"status": "in_transit",
"estimated_delivery": "2024-01-16T17:00:00Z"
}
} π CALLER
β
βΌ
βββββββββββββββββ
β VAPI β β Speech β Text, Text β Speech
β (The Voice) β
βββββββββ¬ββββββββ
β
β POST /webhook π©
βΌ
βββββββββββββββββ
β CAPTAIN CARGO β β FastAPI webhook handler
β (The Brain) β
βββββββββ¬ββββββββ
β
ββββββββββββββΌβββββββββββββ
β β β
βΌ βΌ βΌ
ββββββββββββ ββββββββββββ ββββββββββββ
β ποΈ β β π β β π β
β Cache β β Metrics β β Logger β
β (60s TTL)β β β β β
ββββββ¬ββββββ ββββββ¬ββββββ ββββββ¬ββββββ
β β β
ββββββββββββββββΌβββββββββββββββ
β
βΌ
βββββββββββββββββ
β SANITY β β Your delivery data
β CMS β
βββββββββββββββββ
# Run all 75 tests
pytest tests/ -v
# 75 passed in 3.67s π| Category | What It Tests |
|---|---|
| π§± Unit | Individual functions and classes |
| π Contract | Pydantic model validation |
| π Integration | Full request/response cycles |
Think of this as a "simulated caller" that runs through dozens of scenarios and scores Captain Cargo:
python scripts/eval_replay.py \
--input eval/cases.jsonl \
--server http://localhost:8000 \
--report eval/report.mdSample output:
Total Cases: 50 | Passed: 47 | Accuracy: 94%
Avg Latency: 127ms | P95 Latency: 312ms
Check out eval/report.md for a real example.
Watch Captain Cargo in action β Demo Video
Shows: User calls β Agent asks tracking ID β Tool call β Status response β Fallback when backend's down
π Caller: "Where's my package?"
π€ Vapi (STT): "Where's my package?"
π€ Vapi (NLU): Intent: track_delivery
π€ Vapi β Captain Cargo: POST /webhook {trackingId: "ABC123"}
π¦ Captain Cargo β Sanity: "Give me ABC123"
π¦ Sanity β Captain Cargo: {status: "in_transit", ...}
π€ Captain Cargo β Vapi: {message: "Your package is in transit!"}
π€ Vapi (TTS): "Your package ABC123 is in transit!"
π Caller: "Oh great, thanks!"
π Caller: "Where's TRK999?"
π€ Vapi β Captain Cargo: POST /webhook {trackingId: "TRK999"}
β‘ Captain Cargo β Sanity: (circuit breaker OPEN - Sanity is down)
π€ Captain Cargo β Vapi: {status: "fallback", message: "Having trouble accessing latest data..."}
π€ Vapi (TTS): "I'm having trouble accessing the latest data. Please try again in a moment."
π Caller: "Okay, thanks anyway."
Captain Cargo is provider-agnostic. Your webhook doesn't care about voice stuff β Vapi handles all that.
| Provider | When To Use | Setup |
|---|---|---|
| Deepgram | Fast & accurate | Vapi Dashboard β Add Deepgram Key |
| AssemblyAI | Good streaming | Vapi Dashboard β Add AssemblyAI Key |
| OpenAI Whisper | Highest accuracy | Vapi Dashboard β Add OpenAI Key |
| Provider | When To Use | Setup |
|---|---|---|
| ElevenLabs | Natural, emotional voices | Vapi Dashboard β Add ElevenLabs Key |
| OpenAI | Fast, decent quality | Vapi Dashboard β Add OpenAI Key |
| Azure | Enterprise needs | Vapi Dashboard β Add Azure Key |
- Go to Vapi Dashboard
- Pick your provider
- Enter API key
- That's it. Captain Cargo doesn't need to know. π
captain-cargo/
βββ server.py # FastAPI entry point πͺ
βββ requirements.txt # Python packages π¦
βββ .env.example # Environment template π
βββ README.md # You are here π
βββ specs/ # Master plans πΊοΈ
β βββ 001-voice-agent-prod/
βββ models/ # Pydantic models π§±
β βββ webhook.py # Webhook payload shapes
β βββ delivery.py # Delivery entity shapes
βββ services/ # Business logic π§
β βββ cache.py # 60s TTL cache
β βββ sanity_client.py # Sanity API + circuit breaker
β βββ response_builder.py # Hallucination-safe responses
βββ middleware/ # HTTP middleware π΅
β βββ correlation.py # Correlation IDs
β βββ validation.py # Request validation
βββ utils/ # Utilities π οΈ
β βββ config.py # Environment validation
β βββ logger.py # JSON structured logs
β βββ normalization.py # Tracking ID cleaning
βββ endpoints/ # API endpoints π
β βββ health.py # /healthz, /readyz
β βββ metrics.py # /metrics
βββ scripts/ # Tools π§
β βββ eval_replay.py # Evaluation harness
βββ tests/ # 75 tests passing β
βββ unit/
βββ contract/
βββ integration/
docker build -t captain-cargo .
docker run -p 8000:8000 \
-e SANITY_PROJECT_ID=xxx \
-e SANITY_API_TOKEN=xxx \
captain-cargoapiVersion: apps/v1
kind: Deployment
metadata:
name: captain-cargo
spec:
replicas: 3
containers:
- name: captain-cargo
image: captain-cargo-agent
ports: [8000]
env:
- name: SANITY_PROJECT_ID
valueFrom:
secretKeyRef:
name: sanity-creds
key: project-idSee AGENTS.md for guidelines. We're friendly! π
MIT. Go forth and ship! π’
Captain Cargo β Because your customers deserve to know where their stuff is. π¦β¨