Work / AI platform

An omnichannel AI platform, from first commit to production

How we built a multi-tenant SaaS where AI agents answer customers on WhatsApp, Instagram, Telegram and web chat, and hand the conversation to a human when they should.

Role
Co-founder, lead engineer and product lead
Period
Nov 2024 — present
Context
Joint venture between Pyp System and a Brazilian cloud provider
Stack
NestJS, PostgreSQL, Redis, Python, LangGraph, Qdrant, Go, Nuxt

The problem

Small and mid-size businesses in Brazil run customer service on WhatsApp. Teams are overloaded, answers depend on who is on shift, and managers have little visibility into quality.

We built the answer as a joint venture with a Brazilian cloud provider: AI agents that know each business, answer right away on every channel, and hand the conversation to a person when they should. I lead engineering and product, from architecture to production.

Architecture

Three main services and a few small ones. It is deliberately not a microservice system: services are split only where the runtime has to differ.

Platform architectureWhatsApp traffic goes through a Go gateway to the NestJS platform API; Instagram, Telegram and web chat connect to the API directly. The API stores data in PostgreSQL and uses Redis, and calls a stateless Python AI engine, which uses Qdrant, several LLM providers and SaaS tools over MCP.WhatsAppInstagramTelegramWeb chat widgetGo gatewayconnections · webhooksPlatform APINestJS · Prisma · Socket.IOtenants · authreal-time inboxintegrationsbackground jobsAI engine (stateless)Python · FastAPI · LangGraphagent graphsagentic RAGtool calling over MCPprovider fallbackPostgreSQLRedisQdrantLLM APIs4 providersSaaSvia MCPcontextreply
Scroll →Simplified. The team-facing web app (Nuxt) and the admin back-office also talk to the platform API.
  • Platform API (NestJS). A modular monolith that owns tenants, authentication, the real-time inbox and every integration. PostgreSQL through Prisma, BullMQ on Redis for background work, and Socket.IO for real time.
  • AI engine (Python, FastAPI and LangGraph). Stateless. Each request arrives with the context it needs and leaves with a decision. Each AI workflow is its own LangGraph graph.
  • WhatsApp gateway (Go). A focused service that manages WhatsApp connections and sends signed webhooks to the API.
  • Clients. A Nuxt web app for the teams and an embeddable chat widget for websites.

How a conversation is handled

  1. Retrieve. The agent searches the company's own knowledge (agentic RAG on Qdrant), isolated per tenant.
  2. Act. The model can call tools in a bounded loop, including the customer's connected SaaS tools and a hand-off to a human.
  3. Check. The answer is validated before it goes out. If the agent can't answer safely, a person takes over.

Decisions worth explaining

  1. A modular monolith, not microservices

    For a small team, network boundaries cost more than they protect. Module boundaries are enforced by lint rules on imports instead, and services are split only where the runtime differs: Python for AI, Go for WhatsApp.

    Trade-offMost of the platform is one deploy unit, so deploys had to become boring and safe. That became its own project: zero-downtime deploys.

  2. A provider-agnostic LLM layer

    OpenAI, Anthropic, Gemini and xAI sit behind one interface, with fallback when a provider fails. No feature depends on a single vendor.

    Trade-offWorkflows use the features every provider shares, unless one explicitly opts into something provider-specific.

  3. MCP for integrations, controlled by the platform

    Customers' SaaS tools connect through MCP. The platform decides what each conversation is allowed to use, and the AI engine only executes the calls. When a tool is unavailable, the conversation goes to a human instead of failing quietly.

  4. Owning the WhatsApp layer

    We started on a third-party WhatsApp gateway. It was heavy and did far more than we needed. I replaced it with a focused service in Go: only the operations we use, with supervised reconnection.

    Trade-offIt runs as a single instance by design. A WhatsApp connection can only be held by one process at a time, so this service restarts gracefully instead of going blue-green.

  5. Knowing what every conversation costs

    Every AI request is metered per customer and reconciled with what the model providers actually bill, so the cost of a conversation is measured, not estimated.

Outcome

4channels in production: WhatsApp, Instagram, Telegram and web chat
4LLM providers behind one interface, with fallback
3core services: NestJS platform, Python AI engine and Go gateway

The platform runs in production for business customers and ships several times a day with zero-downtime deploys.

Client names, volumes, financial figures and product internals are withheld. The code is private.