Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

AI Customer-Support Refund Agent

An AI agent that processes or denies e-commerce refunds — and cannot be talked into an unauthorized one, because authorization is enforced in deterministic code, not in the prompt.

Architecture (two-layer enforcement)

  • Layer A — LLM (LangGraph + Claude Haiku): understands intent, runs the conversation, decides which tools to call, communicates. It proposes.
  • Layer B — deterministic policy engine + tools: computes the refund verdict from data + rules and re-validates server-side before any money moves. It ratifies or rejects.

A jailbroken model can call issue_refund(amount=99999) all it wants — the policy engine rejects it.

Stack: FastAPI + LangGraph + Claude Haiku 4.5 · Postgres (app data + LangGraph checkpoints) · React + Vite + Tailwind SPA · browser-native voice mode.


Prerequisites

  • uv (Python package manager — fetches Python itself)
  • Node.js 20+ (for the frontend)
  • Docker (for the local Postgres) — or any reachable Postgres
  • An Anthropic API key (ANTHROPIC_API_KEY)

Local setup

# 1. Clone
git clone https://github.com/rishavnaskar/refund-agent.git
cd refund-agent

# 2. Configure env
cp .env.example .env          # then put your ANTHROPIC_API_KEY in .env
                              # DATABASE_URL already defaults to the local docker Postgres

# 3. Install deps (backend venv via uv + frontend via npm)
make install

# 4. Start the local Postgres (docker) and seed it
make db-up                    # starts postgres:16 on localhost:5432
make seed                     # creates schema + loads the demo CRM

Run it

make api                      # terminal 1 — backend on http://localhost:8000
make web                      # terminal 2 — frontend on http://localhost:5173
# open http://localhost:5173  (Customer Chat + Admin tabs)

make api runs ensure_seeded() on boot, so the schema + demo data are created automatically if the database is empty.

Tests

make db-up                    # tests need Postgres running
make test                     # deterministic policy + red-team suites (no API key needed)

Tests run against TEST_DATABASE_URL if set, else DATABASE_URL, else the local docker Postgres. If no Postgres is reachable they skip with a clear message rather than failing.

Handy commands

Command What it does
make db-up / make db-down start / stop the local Postgres (docker)
make seed (re)create schema + reseed the demo data
make test run the policy + red-team test suites
make api / make web run backend / frontend
make clean stop Postgres and wipe its volume

Configuration (env vars)

Var Required Default Notes
ANTHROPIC_API_KEY ✅ — Claude API key
DATABASE_URL ✅ local docker Postgres Postgres connection string
MODEL — claude-haiku-4-5 Anthropic model id
BASIC_AUTH_USERNAME / BASIC_AUTH_PASSWORD — demo / unset set a password to gate a public deploy
ALLOWED_ORIGINS — * restrict CORS for a split deploy
RETURN_WINDOW_DAYS, ESCALATION_THRESHOLD — 30, 500 policy thresholds

Never commit .env — it's gitignored. .env.example is the template.


Production deploy

State lives in an external Postgres, and the app builds into a single Docker image that serves both the API and the React SPA (one URL, no CORS). It must run as one always-on instance (the SSE engine keeps per-thread queues in memory) — don't add replicas or extra workers.

1. Create the database (Supabase, free tier)

  1. Create a project at supabase.com.
  2. Project → Connect → Session pooler and copy the connection string (use the Session pooler — IPv4, port 5432, supports the prepared statements the checkpointer needs).
  3. That string is your production DATABASE_URL. The app creates its tables automatically on first boot.

2. Deploy the container

The repo has a single-service Dockerfile (builds the SPA, then runs the API). Pick a host that runs an always-on container with HTTPS:

Google Cloud Run (free tier; scale-to-zero)

gcloud run deploy refund-agent \
  --source . \
  --region <your-region> \
  --allow-unauthenticated \
  --min-instances 0 --max-instances 1 \
  --set-env-vars "ANTHROPIC_API_KEY=...,DATABASE_URL=...,BASIC_AUTH_PASSWORD=..."

--max-instances 1 keeps the single-instance guarantee. (Store real secrets in Secret Manager rather than --set-env-vars for anything long-lived.)

Render (one-click blueprint) The included render.yaml defines the service. Render → New → Blueprint → pick the repo, then set ANTHROPIC_API_KEY, DATABASE_URL, and BASIC_AUTH_PASSWORD in the dashboard.

3. Lock it down

Set BASIC_AUTH_PASSWORD so the public URL can't run up your Anthropic usage. Share the URL with the demo username and that password.


Layout

backend/
  app.py               # FastAPI app: lifespan (seed + Postgres checkpointer), SPA serving, basic-auth
  config.py            # model id, DATABASE_URL, policy constants, SUPPORT_CONTACT
  db.py                # Postgres helpers (psycopg3 + connection pool)
  data/                # schema.sql, policy.md, seed_crm.json, seed.py
  agent/               # graph.py, nodes.py, prompts.py, summarize.py, llm.py, tools.py
  gateway/             # routes_chat.py, routes_admin.py, runner.py (SSE), events.py
  tools/               # crm.py, policy_engine.py, refunds.py, rules.py, types.py
  trace/               # store.py (reasoning traces)
  tests/               # test_policy.py, test_redteam.py
frontend/              # React + Vite + Tailwind SPA (chat, admin, voice)
docker-compose.yml     # local Postgres
Dockerfile             # single-service production image (SPA + API)
render.yaml            # Render blueprint

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages