Skip to content
Deska Mulyana
All work

Case study

Cierra

An AI sales agent for WhatsApp sellers

Cierra answers buyer chats on a seller’s own WhatsApp number, negotiates inside a discount limit the seller sets, and saves orders as drafts for the seller to confirm. This page covers how it is built and why.

My role
Go API, WhatsApp gateway, AI service, and infrastructure
Team
Two engineers. Web dashboard mostly by Dimas Danang Aji
Status
MVP built, pilot sign-ups open. Production rollout of the WhatsApp and AI services is pending
Stack
Go, Python, gRPC, PostgreSQL + pgvector, Redis Streams, Next.js, Docker, Terraform
Landing page of Cierra

The problem

Slow replies cost sellers their buyers

  • Sellers lose buyers to slow replies.
  • They repeat the same negotiations all day.
  • Orders get lost in the middle of a chat.

The agent speaks to real customers in the seller’s name. So the hard part is not generating replies. It is making sure the agent can never promise something the seller did not allow.

Architecture

Small services, one queue between them

  1. BuyerWhatsApp
  2. GatewayGo, whatsmeow
  3. QueueRedis Streams
  4. API workerGo
  5. AI servicePython, gRPC
  6. LLMQwen, OpenAI-compatible API
  • PostgreSQL 16 + pgvectorSource of truth and catalog retrieval
  • DashboardNext.js over REST and SSE
  • ObservabilityOpenTelemetry, Prometheus, Grafana, Loki

Hover the diagram to see data flow left to right.

Three boundary rules

  1. 01The API is the only service facing the internet. The gateway, AI service, database, and Redis are reachable only inside the private network.
  2. 02The gateway never talks to the LLM directly. Everything goes through the queue.
  3. 03Every database query carries a tenant context, and the repository layer rejects queries without it.

One message

What happens when a buyer asks for a discount

  1. A buyer writes: “Is there red? Can I get a discount?”

  2. The gateway receives it, drops duplicates by WhatsApp message id, stores it, and pushes it to the inbound stream.

  3. A worker loads the context: seller, customer, chat history, and the seller’s sales playbook.

  4. The AI service checks escalation keywords, retrieves from the seller’s own catalog, generates a structured reply, runs its guards, and falls back to a second model if needed.

  5. If an order is detected, an order draft is created and the owner is notified. If the chat needs a human, it switches to takeover mode.

  6. The reply streams back, is assembled into one message, and goes to the outbound stream.

  7. The gateway sends it with rate limiting and a short pause between messages.

Decisions

Choices that shaped the system, and why

Quality and operations

How it is kept honest

  • 23 Go test files and 5 Python test files, plus an evaluation suite for the sales agent.
  • CI runs lint, tests, and an image build on every change. Deploys are manual from the main branch, run by a self-hosted runner on the production server, with images built locally and no external registry.
  • Infrastructure changes go through Terraform pull requests, not the cloud console.
  • The LLM provider is isolated in its own module, so swapping models or vendors is a contained change.
  • Architecture decisions are written down, and changes arrive as pull requests against the architecture document.

Where it stands

Built, with launch work still ahead

Based on the repository audit of 13 October 2026.

Done

  • Foundation, core API with auth, and data migration
  • WhatsApp gateway
  • AI service, code complete
  • Web dashboard connected to the new API

Before launch

  • Deploy the gateway and AI services to production
  • End-to-end test with two real phones, measuring token cost and time to first reply
  • Alerting, runbooks, and a restore drill
  • Load test

After the MVP

  • Automatic follow-ups
  • Voice-note transcription
  • Real-time inbox
  • TikTok Shop connector, if partner approval comes through

Hiring for a team that ships?

Email works best for roles and project details. For a quick question, WhatsApp is fine too.