Expert AI Labs
Client Case Study · Furniture & Home Goods

Moss Home USA: How Three Connected Automations Freed a Three-Person Team for Higher-Value Work

Expert AI Labs connected order imports, lifecycle synchronization, inventory data, and AI-assisted customer service while preserving deterministic controls and human review.

Published September 24, 2026
16 min read
Douglas Schwartz, Expert AI Labs
3
connected production systems
3
employees redirected to other work
Hourly
order and quote synchronization
6
bounded reply decisions, 2 eligible for auto-send
Executive summary

Moss Home USA is a furniture business with configurable products, dealer relationships, quote and order lifecycles, fabric inventory, and customer questions spread across several systems. Staff spent real hours every day moving records between them, reconciling changes, hunting for order facts, and writing the same replies.

Expert AI Labs built three connected systems: an hourly importer that moves genuine orders and their line items into the operating sheet, an annual review log that tracks every quote as it becomes an order, and an AI-assisted customer-service decision engine that reads support email, looks up order and fabric facts, and returns one bounded action for the workflow layer to execute.

The result Moss Home cares about: the recurring manual workload previously carried by three employees no longer needs them, and all three now spend that time on other business priorities.

The design decision that made it safe: language models interpret requests and draft language. Ordinary code controls the authoritative order, inventory, pricing, and customer records. People keep the decisions that move money, commit inventory, or answer a complaint. We call the system AI-assisted rather than autonomous because that is exactly what it is.

The business and its complexity
Warehouse staff packing an upholstered furniture piece into a shipping carton
Configurable furniture means every order carries line items, fabric choices, and a dealer relationship that all have to stay in sync. Photo: Pexels.

Moss Home sells configurable furniture through dealers, designers, and showrooms, with customer-supplied (COM) fabrics and a catalog of several hundred products. Earlier in the engagement, before the automations described here, the work covered the commerce foundation: BigCommerce catalog architecture, variant modeling for configurable pieces, bulk product imports, merchandising, and seasonal launches.

Day to day, operational truth lives in five places:

  • AMPtab CMS holds quotes and orders from the dealer network, exported as CSV.
  • Smartsheet is the operating record: a Master Open Order sheet, a Basics sheet, annual archives, annual quote-and-order review logs, and a Fabric Master.
  • BarCloud tracks fabric inventory.
  • Gmail receives every customer, dealer, rep, and vendor question at one support inbox.
  • People hold the context that connects all of it.

Three issues made a simple point-to-point integration insufficient:

  1. The same order appears in different lifecycle stages and different annual sheets, so duplicate and stale records are a constant risk.
  2. A partial API response or a missing archive could make a healthy-looking sync re-import completed work.
  3. Customer emails often omit identifiers and mix low-risk questions with commitments that need human judgment.

The system therefore had to be fast on the routine path and conservative the moment data was incomplete, contradictory, or operationally sensitive.

Three design principles
PrincipleImplementation choiceOperational purpose
Authoritative data stays deterministicAMPtab, Smartsheet, BarCloud, and configured reference data supply every factA model can never invent status, inventory, pricing, or policy
Every automation fails closedMissing archives, unavailable sources, uncertain matches, and closed send gates stop the actionIncomplete information becomes a visible exception, not a silent error
Human authority follows business riskRoutine supported cases proceed; transactions, complaints, shortages, and ambiguity require reviewAccountability stays where a wrong answer would cost money or trust
Architecture: three systems, one operating philosophy

Two deterministic pipelines keep the structured record current. The third system uses that record to make bounded decisions about email. Nothing in the AI layer writes to the systems of record.

Sources
  • AMPtab CMS quotes and orders export
  • Gmail support inbox
  • BarCloud inventory + Fabric Master
Reference data
  • Smartsheet Master Open Order, Basics, archives (read for lookups)
  • Contact-role registry (rep, employee, vendor, designer, customer)
Scheduling and orchestration
  • Vercel Cron, hourly
  • n8n workflow: poll, label, POST, route
  • Local launchd / cron fallback with runbook
System 1 · Python on Vercel
  • Master Open Order Importer
  • Filter genuine orders, join line items, dedupe against active + archive sheets, append in batches
  • Aborts if any archive read is unsafe
System 2 · Python on Vercel
  • Order Review Log Sync
  • Latest record wins per normalized order number, route by year, update or insert
  • Process lock, weekday operating window
System 3 · Next.js + Claude
  • Customer Service Decision Engine
  • Clean, classify sender, extract intent, look up facts, apply hard rules
  • Returns one of six decisions; never sends mail itself
Operating record
  • Master Open Order Smartsheet (append only)
  • Annual AMP Order Review Log sheets (update or insert)
Customer actions via n8n
  • Gmail reply (only when every send gate is open)
  • Internal forward of quote requests
  • Label for human review, or do nothing
Evidence and control
  • Supabase review queue and audit table
  • Four independent send gates + intent allowlist
  • Wording lint before any send

The systems share more than a diagram. Both Python pipelines use one core sync function for cloud and local execution, so the fallback path is the production path on a different scheduler. The decision engine publishes a narrow contract (one POST, one decision) so n8n owns everything that touches the inbox.

System 1: Master Open Order Importer

The importer creates the operational view of open orders. Every hour it runs the same six steps against the AMPtab export and the Master Open Order Smartsheet.

Operations employee at a computer surrounded by shipping cartons
Before the importer, new orders reached the operating sheet by hand. Now the sheet is refreshed hourly and a person only looks at exceptions. Photo: Pexels.
  1. Fetch. Download the AMPtab CSV export over an authenticated URL.
  2. Filter. Keep only header rows with status Genuine Order. Quotes and every other status are dropped, along with their line items.
  3. Combine. Join each line item to its order header on the order ID so one Smartsheet row carries order-level fields (customer, PO, date, discount, territory manager) and line-level fields (SKU, item name, unit price, quantity).
  4. Sort. Order the combined rows by date, oldest first.
  5. Deduplicate. The unique key is the AMP Order number. A row is skipped if that number is already on the Master sheet or on either the 2025 or 2026 archive sheet. Existing Master rows are never updated by this job.
  6. Write. Append new rows to the bottom of the Master sheet in batches through the Smartsheet API. Contact columns (account email, TM email) are written as Smartsheet contact objects, not plain strings.

Field mapping

AMP fieldSmartsheet column
ORDER IDOrder ID
UTC DATEOrder Date
DEALER NAMECustomer
ORDER #AMP Order #
PO #Customer PO #
Customer email (dealer extra)ACCOUNT EMAIL (contact)
LI SKU / LI NAMESKU / Item Name
LI UNIT PRICE / LI QUANTITYUnit Price / Qty
DISCOUNT %Discount %
Rep name / rep email (dealer extra)Territory Mgr / TM Email (contact)

The fail-closed rule

Archive verification is a deliberate safety control. If either archive sheet fails to load, is missing the AMP Order number column, or returns zero keys, the run aborts before writing anything. The importer would rather delay new records by an hour than re-import completed orders because one API response came back short.

How it runs

  • Vercel Cron invokes the Python serverless function every hour, 24/7 by default.
  • A bearer secret protects the endpoint. An optional weekday, business-hours gate can be switched on.
  • The function has a 300-second ceiling and logs to standard output.
  • The same core sync can run on a Mac in batches of 50 if cloud execution is unavailable. A written fallback runbook covers turning the local scheduler on and off.
System 2: Order Review Log Sync

The second system preserves the quote-to-order history that operations reviews. It is a one-way sync from the AMPtab quotes-and-orders export into a Smartsheet named AMP Order Review Log, one sheet per year.

  1. Download the export and map AMP columns onto the review schema: order number, dealer, PO, total, status, contact and rep fields.
  2. Keep only rows that carry an AMP Order number.
  3. Latest record wins. Deduplicate by order number, keeping the row with the most recent sales-order date, so a later genuine order replaces an earlier quote instead of sitting beside it.
  4. Translate status into Moss Home operating terms: quote becomes HFC, genuine order becomes Confirmed.
  5. Normalize identifiers. Numeric order numbers are normalized so a leading zero (01162026 versus 1162026) cannot create a second row for the same order.
  6. Route each record to the sheet for its sales-order year; years without a mapping go to a default sheet.
  7. Look up the existing row by AMP Order number and either update it in place or insert a new one at the bottom, in batches of 100.

Continuity controls

  • Vercel Cron runs the function hourly inside a configurable weekday operating window (Pacific time).
  • The local fallback uses a file lock so runs cannot overlap. A lock older than 45 minutes is treated as stale and cleared, including killing a hung process, so one bad run cannot block the workflow indefinitely.
  • The local scheduler stays off while Vercel is healthy; the runbook is the only way it comes back on.
  • There is no web UI and no database. The app is a scheduled integration and nothing more.
System 3: Customer Service Decision Engine

The third system addresses the most judgment-intensive workflow. It is the customer-service brain for the Moss Home support inbox. It reads each message, decides what kind of request it is, looks up order and fabric facts, and returns a reply decision. It does not send mail itself. Sending, labeling, and inbox polling stay in n8n.

The path of one email

  1. An n8n workflow watches the inbox, immediately labels the message so it can never be processed twice, and POSTs it to a protected Next.js endpoint with a bearer token.
  2. The app cleans the email (plain text, HTML as fallback) and isolates the newest authored text from quoted history.
  3. It skips mail it should not answer: Moss system mailboxes, no-reply senders, thank-you-only follow-ups, threads a Moss teammate is already handling, and mail where Moss is only copied.
  4. It classifies the sender from a contact-role registry: sales rep, Moss employee, vendor, showroom or designer, end customer, or unknown.
  5. A language model extracts intent, order numbers, fabric names, and risk signals. Deterministic guards can override that classification.
  6. The app looks up facts in Smartsheet and applies hard rules before any reply is allowed.
  7. It returns one decision. n8n routes on it: send a Gmail reply, forward a quote internally, label for human review, or do nothing.

Six bounded decisions

DecisionMeaning
auto_replySafe to send, and only if every send gate is open and the intent is allowlisted
draft_onlyA draft exists, but a person must decide whether to send it
human_reviewRisky, incomplete, ambiguous, or not approved for automatic sending
no_replyAcknowledgment, spam, or a thread the automation should stay out of
ignore / ignore_outboundDuplicate, skip-list sender, or Moss Home's own outbound mail
errorProcessing failed; no customer-facing action occurs

What it handles, and where it stops

Hands fanning a deck of color swatches over upholstery fabric samples
Fabric questions are the hardest category: stock, width, repeat, and care codes can be answered from inventory data, but holds and yardage commitments stay with a person. Photo: Pexels.
  • Order status. Exact match on AMP Order number, Customer PO number, or Invoice number across the open-orders sheets, the Basics sheet, and yearly archives. Customer wording uses “estimated shipping” and “estimated for completion.” Pending materials, cancelled orders, multiple matches, and missing tracking go to a person. A found order is never asked for its order number again.
  • New furniture quotes. Can be acknowledged and forwarded internally. A fabric price-per-yard question is deliberately not treated as a furniture quote.
  • Fabric. Stock and availability from BarCloud plus the Fabric Master; width, repeat, content, care codes, and COM yardage. Holds, reservations, specifications, care instructions, and unresolved stock stay with a human. The system will not email a mill or a warehouse on its own.
  • Claims and complaints. Product damage, freight damage, freight price, vendor quality updates, and general complaints are separated. A claims-form link is offered only for actual damage, and the URL comes from configuration, never from the email body.
  • Receipts and invoices. A resend request is evaluated against prior sent-mail candidates and held for review rather than inventing a document.
  • Cancellations, returns, refunds, address changes. Always human review.

Send authorization

Sending is fail-closed. A reply can leave only when four independent gates are all open: dry-run mode is exactly off, automatic sending is exactly on, external sending is exactly on, and the intent is on the auto-send allowlist. The allowlist is narrow by design: order status and new furniture quote requests. Everything else is drafted for a person or left unanswered. Closing any one gate is a practical shutdown switch.

Wording is linted before anything can be sent. Replies cannot say “scheduled to ship,” cannot name internal systems, and cannot use em dashes.

Review queue and audit

Held cases can be written to a Supabase review table and read back through a review-queue endpoint. An audit table records each decision. If that configuration is absent the app still runs, but it does not claim a durable audit record. Tests run against mocked Claude and Smartsheet clients so the policy logic can be exercised without live credentials.

Where it came from

The first version of this workflow was a 32-step Zapier automation, Final Order Status Automation, that polled Gmail, classified messages with AI, extracted order and invoice numbers, looked them up in Smartsheet, drafted responses, and routed on branches with delays and attachments. It proved the pattern. The current engine moved that logic into typed, tested code with explicit gates so each new intent could be added one at a time with evidence.

What AI does, what code controls, what people approve

The architecture draws a hard line between language interpretation and operational authority. A fluent answer can still be wrong if it is not tied to a current record.

AI performs

  • Classifies email intent and sender context
  • Extracts order numbers, fabric names, and risk signals
  • Drafts customer language grounded in retrieved facts

Deterministic code performs

  • Authenticates requests and enforces every send gate
  • Matches source records and normalizes identifiers
  • Applies status rules, deduplication, archive checks, and wording lint
  • Owns every write to Smartsheet

People approve

  • Cancellations, returns, refunds, address changes
  • Complaints, claims, shortages, holds, and unclear commitments
  • Any case with conflicting, missing, or sensitive information
Failure handling and safeguards

Five recurring controls keep routine automation from becoming silent operational risk.

  1. Source verification. A workflow stops when an authoritative record cannot be loaded safely. The importer’s archive abort is the clearest example.
  2. Idempotency. Normalized order identifiers, active-and-archive deduplication, Gmail labels applied before processing, and process locks all reduce duplicate work.
  3. Permission gates. The ability to process a message is separated from the authority to send a response. Four environment gates plus an intent allowlist must agree.
  4. Human review. Sensitive transactions, uncertain matches, complaints, shortages, and unsupported requests are routed to people with a labeled thread and, when configured, a queue entry.
  5. Fallback procedures. Both pipelines can run locally on the same core code when the cloud scheduler is unavailable, with a written runbook for cutover and cutback.
Documented limitations
  • Two intents are eligible for automatic sending. Every other intent produces a draft or a review item. That is a choice, not a gap, but it means the human queue is part of the system.
  • Forwarded email. Messages forwarded into the inbox with the original request buried in quoted history have been harder to parse reliably than direct mail.
  • Audit is optional by configuration. Without the Supabase environment the engine still decides correctly but does not persist a durable decision log.
  • Importer is append-only. It never updates an existing Master row; changes to an order after import are handled by people or by the review log.
  • Local fallback is manual. Switching schedulers is a runbook step, not an automatic failover.
Results

The primary result is capacity. Together, the three systems removed the recurring manual workload previously handled by three Moss Home employees, and all three redirected their time toward other business priorities. Routine record movement, lifecycle reconciliation, source lookup, and first-pass email handling no longer require continuous manual attention.

AreaBeforeOperating model now
Order intakeRepeated transfer and checking of new order recordsHourly import with filtering, field mapping, deduplication, and batching
Quote and order reviewManual reconciliation as records moved from quote to confirmed orderLatest state retained by normalized order number and routed by year
Customer serviceStaff interpreted every message and searched several sources before replyingAI-assisted triage and drafting with deterministic fact retrieval and human escalation
Operational continuityAutomation depended on a single execution environmentCloud execution with local recovery procedures and shared core logic

The systems also changed the quality of the operating process. Scheduled imports produce a consistent working record. Identifier normalization and archive checks reduce duplicate risk. Customer replies are tied to current business sources. Unsupported or consequential requests become visible review work instead of improvised answers.

Technology stack
LayerTechnologyRole
CommerceBigCommerceSeveral-hundred-product catalog, variant modeling, bulk imports, merchandising, seasonal launches
Source systemsAMPtab CMS, Smartsheet, BarCloud, GmailAuthoritative order, quote, inventory, fabric, and communication records
Structured automationPython 3, requests, csv, smartsheet-python-sdk, zoneinfoImport, mapping, normalization, deduplication, batch writes, business-hours gate
Decision applicationNext.js 15, React 19, TypeScript, ZodEmail processing, validation, deterministic policy, decision API
Language modelsAnthropic Claude (Haiku for extraction, Sonnet for drafting) with OpenAI fallbackIntent extraction and response generation inside fixed controls
Orchestrationn8n, Vercel Cron, Python and Node serverless functionsInbox polling, scheduled execution, routing, Gmail actions
Review and auditSupabase, application logs, Smartsheet recordsHeld cases, decision records, diagnostics
TestingVitest with mocked Claude and SmartsheetPolicy logic exercised without live credentials
RecoverymacOS launchd / cron, written runbooksFallback execution on the same core code

Secrets, sheet identifiers, export URLs, and customer data are intentionally absent from this write-up.

Why this approach transfers

Many growing companies have the same shape. Important facts live in a commerce platform, spreadsheets, email, an inventory tool, and the heads of a few people. The work looks simple until duplicate records, lifecycle changes, exceptions, and customer commitments show up.

The Moss Home implementation shows how to introduce AI without letting it replace business controls. Deterministic integrations maintain the operating record. AI interprets unstructured language and prepares communication. Humans keep the decisions that change money, commitments, inventory, or customer outcomes.

That division makes the system easy to test, easy to shut down, easy to recover, and easy to extend one supported intent at a time, with evidence, instead of granting broad authority up front. It is the same operating model Expert AI Labs runs on its own production systems.

Running a business on spreadsheets, email, and three people who know where everything is?

We will map your order, inventory, and support flows, show you which steps deterministic code should own, where AI helps, and where a person has to stay in the loop.