NShop
AI features

Shopping agent (ADK + AG-UI)

The hidden, more capable assistant that actually takes action on your behalf.

NShop ships a second AI surface at /{locale}/x/assistant. It's not linked from the storefront and is noindexobscurity, not access control — because the real protection is the per-tool authentication described below.

The shopping agent is a separate Python Cloud Run service built on three pieces:

  1. ADK (Anthropic's Agent Development Kit) for the agent loop and tool orchestration.
  2. AG-UI for generative UI — the agent doesn't just reply in text, it renders product cards, tables, and order summaries inline.
  3. Vertex Gemini 2.5 Flash for the underlying model, pinned to europe-west4.

How the request flows

shopper → Next.js BFF (/api/agent/[...path])
              ↓ verifies __session cookie + tenant
              ↓ mints 5-minute HS256 JWT with { uid?, tenantId, role?, threadId }
              ↓ proxies AG-UI SSE

         Python agent (ADK + AG-UI)
              ↓ verifies JWT → Principal
              ↓ runs tool calls; each tool re-checks Principal

         Firestore / Storage / Stripe (server-side)
  • The Next.js app is the only thing the shopper's browser sees. It resolves the tenant from the subdomain (getTenantSlug()), verifies the session, and proxies the SSE stream.
  • The JWT is short-lived (5 minutes) and signed with a secret in Secret Manager. The Python service rejects anything that doesn't verify.
  • Inside the Python service, the Principal is attached to every tool call. Public tools accept an anonymous principal; private tools (cart, orders, preferences) reject it.

What it can render

  • Product cards with image, price, stock, and an Add to cart button wired to the agent itself — no leaving the conversation to act.
  • Order detail blocks with status timeline, tracking link, and items.
  • Comparison tables when the shopper asks "which of these is better for…".
  • Preference summaries ("I have you down for size M and a preference for organic cotton — should I prioritize that?").

What makes it "agentic"

The agent decides which tools to call and in what order. A single turn might:

  1. Run semantic search.
  2. Fetch full detail on two candidates.
  3. Compare them.
  4. Read the shopper's saved size preference.
  5. Render an Add-to-cart card for the right variant.

The shopper writes one sentence; the agent does the rest.

Persistence

  • Logged-in threads live in Firestore at /chat_threads.
  • Anonymous threads live in localStorage, signed with an HMAC key stored server-side at /anonymous_chat_keys/{threadId} (server-only access, 7-day TTL). The key prevents anyone from forging history that the agent later trusts.
  • A shopper can sign in mid-conversation and adopt their anonymous thread into their account.

Why a separate service?

ADK is a Python framework. Putting it in its own Cloud Run service (python-agent/) lets it scale independently, deploy on its own schedule (path-filtered Cloud Build trigger), and use a different model without rebuilding the Next.js app.

See the runbook in docs/runbooks/agent-service.md for operational details (deployment, secrets, logs).

On this page