Add the public URL at the top, plus a "Try it yourself" section listing the four mock orders, the happy paths, the sad paths, and the categories of refusal the guardrails are designed to enforce — so a first-time visitor can poke at every flow without reading the source.
3.8 KiB
Bookly
Try it live: https://bookly.codyborders.com
A conversational customer support agent for a fictional online bookstore.
The agent handles two depth use cases (order status and returns) and one breadth use case (policy questions) over a vanilla HTML chat UI, backed by Anthropic Claude with a four-layer guardrail strategy. The full agent design rationale lives in DESIGN.md.
Try it yourself
Open https://bookly.codyborders.com and chat with the agent. The store is fictional and the data is fake — use the orders below to walk through the happy paths and the failure modes the guardrails are designed to catch.
Orders in the database
| Order ID | Customer | Status | Notes | |
|---|---|---|---|---|
| BK-10042 | Sarah Chen | sarah.chen@example.com |
delivered | The Goldfinch + Sapiens, $36.98. Delivered 15 days ago — inside the 30-day return window. |
| BK-10089 | James Murphy | james.murphy@example.com |
shipped | Project Hail Mary, $18.99. Shipped 4 days ago, not yet delivered. |
| BK-10103 | Sarah Chen | sarah.chen@example.com |
processing | Tomorrow, and Tomorrow, and Tomorrow, $17.99. Ordered yesterday, not yet shipped. |
| BK-9871 | Maria Gonzalez | maria.gonzalez@example.com |
delivered | The Midnight Library, $15.99. Delivered 55 days ago — past the 30-day window. |
Things to try
Happy paths
- "What's the status of BK-10089?" then provide the email — should show the shipped status and tracking number.
- "I want to return BK-10042. My email is sarah.chen@example.com." — should walk through eligibility, summarize the refund terms, ask for confirmation, then issue an RMA.
- "How do I reset my password?" — should quote the verbatim FAQ entry.
- "What's your shipping policy?" — same pattern, verbatim quote.
Sad paths the agent should handle gracefully
- "Where is my order?" with no order ID — should ask for the BK-prefixed ID.
- Sarah Chen has two orders — say "I want to return my order" with her email and the agent should ask which one.
- "I want to return BK-10089" — should refuse because the order has not been delivered yet.
- "I want to return BK-9871" with Maria's email — should refuse because the order is past the 30-day window.
- Provide the wrong email for an order — the agent should say it can't find a match (privacy: no enumeration of which IDs exist).
Things the agent should refuse
- "Recommend me a good mystery novel."
- "Which book should I read next?"
- "Can you change my shipping address?"
- "I want to dispute a charge on my credit card."
In every refusal case the agent uses the same template and offers to redirect you to something it can help with.
Stack
- Python 3.11+, FastAPI, Uvicorn
- Anthropic Claude (Sonnet) with prompt caching
- Vanilla HTML / CSS / JS chat frontend (no build step)
- Pytest
Setup
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
cp .env.example .env
# edit .env and set ANTHROPIC_API_KEY
Run locally
./venv/bin/uvicorn server:app --host 127.0.0.1 --port 8014
Then open http://127.0.0.1:8014 in a browser.
Tests
./venv/bin/python -m pytest tests/ -v
Tests mock the Anthropic client, so no API key or network access is required.
Project layout
agent.py System prompt, guardrails (layers 1, 2, 4), agentic loop
tools.py Tool schemas, handlers, SessionGuardState (layer 3)
mock_data.py Orders, return policy, FAQ policies
server.py FastAPI app: /api/chat, /health, static mount
config.py pydantic-settings config loaded from .env
static/ index.html, style.css, chat.js
tests/ test_tools.py, test_agent.py
deploy/ systemd unit + nginx site config for the production droplet
Design
See DESIGN.md for the architecture, conversation design, hallucination and safety controls, and production-readiness tradeoffs.