Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

 
 

Repository files navigation

Northwind Support Copilot

A realistic, agentic support-operations console for a fictional e-commerce store ("Northwind Goods"). It is a support-ticket inbox plus a standalone conversational copilot, backed by a real SQLite database seeded with customers, orders, products, tickets, and help-center articles.

The app was built as a test subject for LLM/agent observability tooling: it deliberately exercises many distinct AI code paths — streaming chat, multi-step tool-calling loops, structured output, and embeddings-based RAG — plus real DB reads/writes and an intentionally flaky tool that produces errors.

It ships with no observability/instrumentation SDK of any kind — all AI calls are funnelled through a few centralized modules so instrumentation can be added cleanly later.

Stack

  • Next.js 16 (App Router) + React 19 + TypeScript + Tailwind CSS v4
  • Vercel AI SDK v7 (ai, @ai-sdk/react) with the OpenRouter provider — chat, tools, and generateObject
  • OpenAI client → OpenRouter for embeddings (a second, distinct LLM path)
  • SQLite + Drizzle ORM (better-sqlite3)

Getting started

pnpm install
cp .env.example .env.local     # then add your OpenRouter API key
pnpm db:push                   # create the SQLite schema
pnpm db:seed                   # seed data (+ embed help articles if key is set)
pnpm dev                       # http://localhost:3000

If you seed before setting OPENROUTER_API_KEY, the relational data is still created and the app runs; run pnpm db:embed afterward to build the help-center embeddings that power semantic search.

Environment

Variable Default Purpose
OPENROUTER_API_KEY – Required for all AI features
OPENROUTER_MODEL openai/gpt-4o-mini Chat/agent model (needs tool-calling + JSON)
OPENROUTER_EMBEDDING_MODEL openai/text-embedding-3-small RAG embeddings
DATABASE_URL file:./northwind.db SQLite file
CHAOS_FAILURE_RATE 0.25 Probability the checkInventory tool fails

What the agent can do (tools)

Reads: lookupCustomer, getCustomerOrders, getOrder, searchProducts, checkInventory (flaky), searchHelpArticles (RAG). Writes: issueRefund, updateTicketStatus, postTicketReply, escalateTicket, createTicket.

Surfaces

  • Inbox (/inbox) — ticket list · thread · customer context, with a ticket-scoped copilot and two structured-output actions (Summarize thread, Draft reply).
  • Copilot Chat (/chat) — a standalone agent with all tools and persisted conversation history.

Things to try (each generates rich agent activity)

  1. Open a ticket → Summarize thread, then Draft reply (structured output).
  2. In the ticket copilot: "Look up this customer and list their recent orders" (multi-tool read loop).
  3. "Issue a refund for their most recent order" (a write tool that mutates the DB).
  4. "What's our return policy for opened items?" (embeddings RAG).
  5. Ask "Is SKU ELE-SPEAKER in stock?" a few times — the warehouse tool fails intermittently by design.
  6. In /chat: "Find the customer for ticket #2, check if the item they mention is in stock, and draft an apology" (a longer tool chain).

Project layout

app/                 # routes: /inbox, /chat, and /api/*
  api/chat/          # streaming agent endpoint (the main tool loop)
  api/tickets/[id]/  # summarize + draft-reply (generateObject) and reads
components/          # UI (InboxClient, ChatClient, CopilotPanel, ToolCallCard…)
lib/ai/              # provider, embeddings, rag, tools, agent  ← the AI core
lib/queries.ts       # DB read helpers
db/                  # schema, client, seed + embed scripts

Scripts

pnpm dev · pnpm build · pnpm start · pnpm db:push · pnpm db:seed · pnpm db:embed

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages