case studyStore Support Agent
A support agent that checks real stock and won't be talked into a discount.
Hackathon build · live public demo · by Firas Ridene
Loomhaus is an AI customer-support agent for a small online store. An orchestrator agent in n8n dispatches to three subagents (inventory, order capture, knowledge base) wired to Google Sheets, Notion and Supabase. The stock decision is made by workflow logic, not by the model, and four independent layers defend against prompt injection. Built in about five hours for the Multi-App AI Agent Hackathon, and tested against the live systems.
- Context
- Multi-App AI Agent Hackathon, September 2026
- Build time
- About 5 hours
- Type
- Working prototype with a public demo, not a production deployment
- Stack
- n8n, OpenAI gpt-4.1-mini, Supabase (pgvector, Realtime), Notion, Google Sheets, Next.js, Vercel
Problem and target user
A small clothing brand gets the same questions every day: is this in stock, how do returns work, can I order two. A basic chatbot can answer questions, but it doesn't know what's on the shelf, it can't take an order, and it will happily promise something the store can't deliver.
The hard moments have real consequences: confirming stock that isn't there, two customers racing for the last units, and a customer talking the bot into a discount. The hackathon asked for a multi-step agent connected to at least three apps, with proof that it works, so I built around those three failure modes and tested each one.
Constraints and requirements
- Connect to at least three real apps: Google Sheets as the inventory, Notion as the order list, Supabase as the store's knowledge base.
- Never promise stock that is already reserved for another order.
- Never leak exact stock counts, other customers' details, or internal instructions.
- Fail honestly: if an app is down, tell the customer and write nothing half-finished.
- Judges can't open the store's Notion or Google accounts, so the result has to be visible from a public dashboard.
Architecture
Everything runs in a single n8n workflow. Every message first passes an injection filter. Clean messages go to an orchestrator agent (gpt-4.1-mini), which can only act through three subagents, each a branch of the same workflow:
- check_inventory reads the Sheet. An n8n IF node compares stock, reserved units and the quantity asked for, and the agent only ever hears back "available" or "not confirmed".
- capture_order checks stock again, writes the order to Notion, reserves the units in the Sheet, then re-reads the Sheet to make sure nothing was over-reserved.
- answer_from_kb runs a vector search over the store's policies in Supabase and answers only from what it finds.
- A fulfillment sync polls Notion every 30 seconds. When the team marks an order Fulfilled, stock and reservations update in the Sheet, and the same order is never applied twice.
- n8n mirrors every change to Supabase, and a Next.js dashboard on Vercel shows it live through Supabase Realtime. The dashboard only displays data. Every decision happens in n8n.
Key engineering decisions
The model never decides availability. Stock numbers never reach it, so it can't leak them or round them in the customer's favour. When two customers want the last two hoodies, the second one is told availability can't be confirmed and is logged as a Follow-up in Notion, instead of being sold stock already promised to someone else.
Prompt-injection defence is layered, so that no single layer has to be perfect:
- No dangerous tools. Nothing in the system can change a price, apply a discount, read other customers' orders or return stock counts.
- A pre-filter in n8n catches common attacks (instruction overrides, fake admin mode, hidden system tags, discount requests) and sends a fixed reply. The model never sees those messages.
- The agent's instructions treat customer text as information, never as commands, and include a canary word that would reveal a prompt leak.
- Replies must fit a fixed schema (intent and reply_text) with no field for a price, and a final check blocks any reply containing the canary or a stock count.
My contribution
Every commit in the public repository is mine: the Python scripts that generate and deploy the n8n workflow, the Supabase schema and knowledge-base ingestion, the Notion and Sheets setup, the Next.js dashboard, and the test harness that checks the live system.
Verified outcomes
Every test runs against the live system. Instead of trusting the agent's reply, each test reads Notion, Google Sheets and Supabase back through their APIs, and the raw results are committed to the repository.
- Prompt injection: 10 of 10 attacks blocked and 3 of 3 normal questions answered. The filter stopped 6 attacks, and the other layers stopped the remaining 4.
- Race for the last units: 21 of 21 checks passed. The second customer was not confirmed, was logged as a Follow-up, and the Sheet was unchanged.
- Broken Notion connection: 8 of 8 checks passed. The customer got an honest error, nothing was reserved, and the error was logged.
- Fulfillment sync: the Sheet updated 36.5 seconds after an order was marked Fulfilled, and the order was never applied twice.
Limitations
- It's a hackathon prototype for a fictional store, not a system serving real customers.
- The public demo is shared by every visitor, so state left by one person is visible to the next until someone hits Reset.
- The pre-filter is pattern-based. On its own it stopped only 6 of the 10 attacks, which is why the system doesn't rely on it alone.
- The adversarial test set is 10 prompts. That's evidence the layers work as designed, not a guarantee against every attack.
Source and demo
- Try the live demo ↗
- Watch the 2-minute demo ↗
- Source code on GitHub ↗
- Raw prompt-injection results ↗
Want something like this for your business, or hiring for an AI engineering role? I'm Firas Ridene, AI Engineer in Tunis, Tunisia, focused on Generative AI & Multi-Agent Systems.