Security and performance fixes addressing a comprehensive review: - Server-issued HMAC-signed session cookies; client-supplied session_id ignored. Prevents session hijacking via body substitution. - Sliding-window rate limiter per IP and per session. - SessionStore with LRU eviction, idle TTL, per-session threading locks, and a hard turn cap. Bounds memory and serializes concurrent turns for the same session so FastAPI's threadpool cannot corrupt history. - Tool-use loop capped at settings.max_tool_use_iterations; Anthropic client gets an explicit timeout. No more infinite-loop credit burn. - Every tool argument is regex-validated, length-capped, and control-character-stripped. asserts replaced with ValueError so -O cannot silently disable the checks. - PII-safe warning logs: session IDs and reply bodies are hashed, never logged in clear. - hmac.compare_digest for email comparison (constant-time). - Strict Content-Security-Policy plus X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy via middleware. - Explicit handlers for anthropic.RateLimitError, APIConnectionError, APIStatusError, ValueError; static dir resolved from __file__. - Prompt cache breakpoints on the last tool schema and the last message so per-turn input cost scales linearly, not quadratically. - TypedDict handler argument shapes; direct block.name/block.id access. - functools.lru_cache on _get_client. - Anchored word-boundary regexes for out-of-scope detection to kill false positives on phrases like "I'd recommend contacting...". Literate program: - Bookly.lit.md is now the single source of truth for the five core Python files. Tangles byte-for-byte; verified via tangle.ts --verify. - Prose walkthrough, three mermaid diagrams, narrative per module. - Woven to static/architecture.html with the app's palette (background #f5f3ee) via scripts/architecture-header.html. - New GET /architecture route serves the HTML with a relaxed CSP that allows pandoc's inline styles. Available at bookly.codyborders.com/architecture. - scripts/rebuild_architecture_html.sh regenerates the HTML after edits. - code_reviews/2026-04-15-1433-code-review.md captures the review that drove these changes. All 37 tests pass. |
||
|---|---|---|
| code_reviews | ||
| deploy | ||
| scripts | ||
| static | ||
| tests | ||
| .env.example | ||
| .gitignore | ||
| agent.py | ||
| Bookly.lit.md | ||
| config.py | ||
| DESIGN.md | ||
| mock_data.py | ||
| README.md | ||
| requirements.txt | ||
| server.py | ||
| tools.py | ||
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.