Jagdeep Singh

Available

Projects

Cartographer

An autonomous shopping agent that builds a personalised cart conversationally — one product category at a time, with the customer choosing at every step.

github.com/jagdeepbanga/Cartographercartographer-drab.vercel.app

The problem

Product search makes the customer do the translating. Someone who knows they have sensitive skin and £150 to spend still has to turn that into categories, filters and comparisons themselves. Cartographer inverts it: the customer states the goal in their own words, and the agent does the decomposition — planning which categories the goal implies, then working through them one at a time.

How it works

The customer's opening message goes to an agent loop built on the Vercel AI SDK, which streams tokens and tool calls back over server-sent events. The agent's first move is always to produce a shopping plan, rendered in the UI as a card so the customer can see the route before any product appears. It then works the plan one category at a time: a search tool queries Postgres by category and JSONB attribute filters and returns exactly three options, the customer picks one, and an add-to-cart tool writes the choice and updates the cart panel. The agent never adds a product on its own — every item in the final cart was chosen by a human. What makes it more than a demo is that neither the catalogue nor the model is compiled in: the tool schemas and the system prompt are both generated from a domain config file at startup.

ClientNext.js chat, consumes SSE, picks each product
Agent loopVercel AI SDK streamText, plan then category by category
ProvidersAnthropic, OpenAI, Google, OpenRouter
Tool registryfour Zod-typed tools, built from the domain config
Postgresproducts with JSONB facets, sessions, cart items

Stack

  • TypeScript
  • Next.js
  • Vercel AI SDK
  • Postgres
  • SSE
  • Zod

Decisions and trade-offs

The domain is a config file, not code

Categories and facets live in a JSON config, and both the tool schemas and the system prompt are generated from it at startup. Swapping the store from beauty to electronics is an env var, not a refactor — the agent simply knows what it is selling. Hardcoding the catalogue would have been faster and would have made the second domain a rewrite.

Provider-agnostic through the AI SDK

Streaming and tool calling are normalised across Anthropic, OpenAI, Google and OpenRouter, so the provider is one env var and no code changes. Committing to a single provider's SDK would have meant rewriting the loop to evaluate a different model.

SSE rather than WebSockets

The stream only runs one way — server to client. SSE reconnects on its own and passes through ordinary HTTP infrastructure; a bidirectional socket would have been more surface for no gain.

A mock mode that needs no API key

MOCK_LLM=true runs a scripted agent loop against the real database, real cart and real streaming. It keeps the demo cheap to show and gives the UI a deterministic path to be tested against.

What it does not do

There is no checkout, no payment and no accounts — the cart is the end of the journey, keyed to a session. It sells one domain at a time rather than searching across several, and the electronics config ships without seed data. The catalogue is mock data, not a real retailer feed.

Next project: SkillsAll projects