Inspiration

Indonesia's 65 million SMEs lose deals daily to one boring failure: sales follow-up. The owner is doing five jobs at once, leads sit cold for a week, and the prospect quietly buys from someone else. Existing "AI sales tools" stop at "draft an email" — but the actual money only moves when payment lands.

Niaga is built for that gap: a seven-agent team that does not just send email. It argues with itself about each lead, writes in real business Indonesian, classifies replies, and closes the loop by sending a DOKU payment link. The owner defines the offer once; the agents do the rest.

What it does

Define one Indonesian Ideal Customer Profile and one offer. Niaga then runs a continuous autonomous loop:

# Agent Role
1 Prospector Enriches each lead with web data
2 Bull Argues for pursuing the lead
3 Bear Argues against — surfaces real risks
4 Judge Renders an explainable verdict
5 Outreach Drafts and sends Bahasa Indonesia email
6 Reply Classifies the prospect's response by intent
7 Closer Decides if and when to fire a DOKU payment link

Plus an AfterCare agent triggered by the DOKU webhook on payment receipt, and a deterministic Orchestrator that strings them together with no human clicks between "lead in" and "money in."

Everything streams to a live agent feed UI so the operator can watch the agents think, debate, and act in real time.

How we built it

  • LLM: Google Gemini via Vertex AI. gemini-2.5-pro for reasoning agents (Judge, Outreach, Closer), gemini-2.5-flash for fast classifiers (Prospector, Bull, Bear, Reply, AfterCare).
  • Backend: FastAPI + SQLAlchemy + WebSockets for the agent feed, deployed to Google Cloud Run.
  • Frontend: React + Vite + TypeScript + Tailwind, with id/en i18n.
  • Email: Gmail SMTP for send, IMAP for receive, with quoted-reply stripping so we hand the LLM clean text.
  • Payment: DOKU Checkout v1 API in sandbox, fully wired through the HMAC signing scheme and webhook verification.
  • Infra: Cloud Run with min-instances=1 so the IMAP poller is always alive — judges do not need to click anything for the system to react to a reply.

Challenges we ran into

  • DOKU's HMAC signature is not what the stub assumed. The first sandbox call returned invalid_signature. The spec requires newline-separated Client-Id / Request-Id / Request-Timestamp / Request-Target / Digest with base64-encoded SHA-256 digest and an HMACSHA256= header prefix. Fixed, and now generates real staging.doku.com/checkout-link-v2/... links end-to-end.
  • A live personal Gmail with 10,000+ unread emails drowns a naive SEARCH UNSEEN poller. We narrowed to UNSEEN SINCE <today-2d> with a hard cap so the poll always completes within a run's lifetime.
  • The original inbox_loop was tied to a specific AgentRun and died when the run completed — meaning the judge would have had to manually start a run for every reply to be detected. Refactored into a single always-on global_inbox_loop started by the FastAPI lifespan, paired with --min-instances=1 so the container never scales to zero.

Accomplishments we are proud of

  • A real autonomous loop: in the live demo, you reply to the outreach email and within ~15 seconds the system has classified your intent, decided whether to send a payment link, and (if you said "kirim payment link") dropped a real DOKU sandbox checkout URL into the thread — without any operator click.
  • Adversarial qualification with explainable verdicts: every lead carries a permanent record of why the Bull pushed for it, why the Bear pushed back, and how the Judge resolved it.
  • True Bahasa Indonesia outreach, not English-with-translate. Business-formal register by default, switchable via the Sales Voice setting.

What we learned

  • LLMs are unreliable JSON producers; every agent boundary needs a _parse_error fallback that gracefully degrades the lead's status instead of crashing the run.
  • "Always-on" is harder than it sounds on Cloud Run: you need lifespan hooks, min-instances >= 1, and an external state store (not ephemeral SQLite) before the demo is truly production-shaped.
  • Adversarial multi-agent design (Bull/Bear/Judge) catches more bad leads than a single classifier — the Bear keeps the Bull honest in a way that a higher temperature alone cannot.

What is next for Niaga

  • Switch SQLite → managed Postgres (Neon / Cloud SQL) so the campaign survives a deploy.
  • Wire DOKU's webhook URL per payment method so the AfterCare agent fires reliably on every paid transaction.
  • Indonesian-specific lead finding via Google Maps Places + LinkedIn enrichment.
  • A quota / cost cap dashboard so SME owners can confidently leave the agents running overnight.

Built With

Share this project:

Updates