ANTIGRAVITY LABJP
Articles/Agents & Manager
Agents & Manager/2026-04-26Advanced

Building a Subscription SaaS on Antigravity Multi-Agent — Role Splits, Quotas, and Stripe Integration That Actually Stick

Antigravity multi-agent is fun to demo. Turning it into the core of a paying subscription SaaS is a different game. Here's the implementation playbook — agent role splits, idempotent task queues, Stripe metered billing, and retention — with working TypeScript code.

Antigravity322Multi-Agent12Subscription2Stripe14SaaS10Indie Dev4Recurring Revenue

"Multi-agent demos are fun. Charging actual money for it every month is a different problem." If you've felt that gap, you're not alone — when I first built on Antigravity multi-agent, I spent the first month producing impressive demos and zero revenue.

What changed when I made it a real subscription business was treating multi-agent as continuous value instead of as a feature. A clever trick the user fires once becomes boring within three months. An agent team that quietly handles a piece of the user's recurring work each day or each week becomes something they actively miss when it's gone — and that's the foundation for low churn.

This article is the implementation playbook for turning Antigravity multi-agent into recurring revenue. Four pillars: agent role splits, task queue design, Stripe integration, and cost control. Working code, the reasoning behind each decision, and the trade-offs.

Designing Multi-Agent for "Continuous Value"

Subscriptions reward products that the user wants to keep paying for. A useful one-shot feature loses freshness fast. A team of agents that processes the user's daily or weekly recurring work, on the other hand, gets harder to leave with each month it operates.

Antigravity multi-agent fits that "continuous" shape well. Split work across multiple specialized agents, run them on a recurring schedule, and the SaaS stops being "a tool I tried" and becomes "a teammate I rely on."

Two use cases that pair especially well with subscriptions:

  • Daily monitoring + summary: news, transactions, social mentions — anything that arrives daily, agents summarize and email out.
  • Weekly reports: project status, revenue rolling, customer support digest — the weekly reports a human currently writes by hand, automated.

Both have a "value compounds month over month" property. That's the starting point for designing multi-agent × subscription.

Three-Layer Agent Split — Orchestrator, Specialist, Watchdog

The first wall when you start coding is "who does what." The split I run with:

1. Orchestrator — controls the flow, picks which specialist to invoke 2. Specialists — concrete tasks (summarize, extract, translate, generate, notify) 3. Watchdog — quality-checks specialist outputs and triggers redo when needed

import { Agent, AgentSession } from "@antigravity/sdk";
 
interface OrchestrationRequest {
  userId: string;
  taskType: "daily_summary" | "weekly_report" | "watchlist_alert";
  payload: Record<string, unknown>;
}
 
async function orchestrate(env: Env, req: OrchestrationRequest): Promise<{ status: string; resultId: string }> {
  const session = new AgentSession({ apiKey: env.ANTIGRAVITY_API_KEY });
 
  // 1. Quota check tied to Stripe subscription state
  const allowed = await checkSubscriptionQuota(env, req.userId, req.taskType);
  if (!allowed) return { status: "quota_exceeded", resultId: "" };
 
  // 2. Dispatch to the right specialist
  let result: string;
  try {
    switch (req.taskType) {
      case "daily_summary":
        result = await dailySummaryAgent(session, req.payload);
        break;
      case "weekly_report":
        result = await weeklyReportAgent(session, req.payload);
        break;
      case "watchlist_alert":
        result = await watchlistAgent(session, req.payload);
        break;
    }
 
    // 3. Watchdog quality check
    const qualityOk = await qualityCheckAgent(session, result);
    if (!qualityOk) {
      result = await fallbackAgent(session, req.payload);
    }
 
    // 4. Persist + notify
    const resultId = await persistResult(env, req.userId, req.taskType, result);
    return { status: "success", resultId };
  } catch (error) {
    console.error("orchestrate failed:", error);
    return { status: "error", resultId: "" };
  }
}

The non-obvious lever here is the watchdog layer. The single biggest churn driver in multi-agent SaaS is inconsistent output quality. One weird summary in twenty makes users start mentally questioning the subscription. A watchdog that catches obvious failures and triggers a fallback path quietly preserves trust over months.

Task Queues + Idempotency — Don't Bill Twice

Recurring scheduled tasks are easy to accidentally double-execute when timeouts or retries fire. Double-execution causes two problems: duplicate user notifications, and duplicate agent costs.

Idempotency keys solve both with one mechanism.

import { z } from "zod";
 
const TaskSchema = z.object({
  userId: z.string(),
  taskType: z.string(),
  scheduleDate: z.string(), // YYYY-MM-DD
  payload: z.record(z.unknown()),
});
 
type Task = z.infer<typeof TaskSchema>;
 
async function runScheduledTask(env: Env, task: Task): Promise<{ status: string }> {
  const idempotencyKey = `task:${task.userId}:${task.taskType}:${task.scheduleDate}`;
  const existing = await env.TASK_KV.get(idempotencyKey);
  if (existing) {
    return { status: "already_executed" };
  }
 
  // Take the lock first; visible to other workers as "running"
  await env.TASK_KV.put(idempotencyKey, "running", { expirationTtl: 3600 });
 
  try {
    const result = await orchestrate(env, task);
    await env.TASK_KV.put(idempotencyKey, JSON.stringify(result), {
      expirationTtl: 60 * 60 * 24 * 7,
    });
    return { status: "success" };
  } catch (error) {
    console.error("task failed:", error);
    await env.TASK_KV.delete(idempotencyKey);
    throw error;
  }
}

The grain userId + taskType + scheduleDate is what makes "same user, same task, same day" naturally exclusive. The 1-hour TTL on the lock means a stuck execution releases automatically and becomes retryable later — without a manual recovery step.

Stripe Subscription Integration — Quota and Cost Caps

Margin in multi-agent SaaS is decided by agent invocation cost. If you charge $30/month per user and your agents cost $15 to run that user's tasks, you barely have a business.

Cap both monthly task counts and monthly cost per plan, on every invocation.

interface PlanLimits {
  monthlyTaskLimit: number;
  monthlyCostLimitUsd: number;
}
 
const PLAN_LIMITS: Record<string, PlanLimits> = {
  starter: { monthlyTaskLimit: 30, monthlyCostLimitUsd: 5 },
  standard: { monthlyTaskLimit: 100, monthlyCostLimitUsd: 15 },
  plus: { monthlyTaskLimit: 300, monthlyCostLimitUsd: 40 },
};
 
async function checkSubscriptionQuota(
  env: Env,
  userId: string,
  taskType: string
): Promise<boolean> {
  const subscription = await getActiveSubscription(env, userId);
  if (!subscription) return false;
  const limits = PLAN_LIMITS[subscription.planId];
  if (!limits) return false;
 
  const month = new Date().toISOString().slice(0, 7);
  const usageKey = `usage:${userId}:${month}`;
  const usage = (await env.USAGE_KV.get(usageKey, "json")) as { taskCount: number; costUsd: number } | null;
  const current = usage ?? { taskCount: 0, costUsd: 0 };
 
  if (current.taskCount >= limits.monthlyTaskLimit) return false;
  if (current.costUsd >= limits.monthlyCostLimitUsd) return false;
  return true;
}
 
async function recordUsage(env: Env, userId: string, costUsd: number): Promise<void> {
  const month = new Date().toISOString().slice(0, 7);
  const usageKey = `usage:${userId}:${month}`;
  const usage = (await env.USAGE_KV.get(usageKey, "json")) as { taskCount: number; costUsd: number } | null;
  const next = {
    taskCount: (usage?.taskCount ?? 0) + 1,
    costUsd: (usage?.costUsd ?? 0) + costUsd,
  };
  await env.USAGE_KV.put(usageKey, JSON.stringify(next), { expirationTtl: 60 * 60 * 24 * 35 });
}

Without the cost cap, a single long-context summarization can eat a month's margin. Without the task cap, a user can degrade quality by hammering the agents non-stop. Both caps together protect both margin and experience.

Hybrid Pricing — Flat Subscription + Overage

A pure flat subscription leaves heavy users unprofitable and light users overpaying. A pure usage-based plan stresses users with unpredictable bills. Hybrid is the saner middle:

  • Standard: $29/month (up to 100 tasks)
  • Overage rate: $0.30/task above the cap
  • If a month's total bill exceeds 2× the standard plan, auto-suggest the next tier

Implement the overage piece with Stripe Metered Billing.

import Stripe from "stripe";
 
async function reportOverageUsage(env: Env, userId: string, overageCount: number): Promise<void> {
  if (overageCount <= 0) return;
  const stripe = new Stripe(env.STRIPE_SECRET_KEY, { apiVersion: "2025-09-30.clover" });
  const subscriptionItemId = await getMeteredItemId(env, userId);
  await stripe.subscriptionItems.createUsageRecord(subscriptionItemId, {
    quantity: overageCount,
    timestamp: Math.floor(Date.now() / 1000),
    action: "increment",
  });
}

Hybrid keeps predictability for the user while keeping margin defense for you. Pure usage-based feels punitive after a busy week. Flat-with-overage gives the user the comfort of a known monthly figure plus a graceful escape hatch when usage spikes.

Cancel Flow — Branch by Reason, Not by Volume of Discount

Most cancellations in multi-agent SaaS trace back to "haven't used it lately." Stripe Customer Portal's default flow takes that exit signal at face value. Custom retention flow earns back 20–30% of cancel intent in my experience.

Branch retention offers by reason, not by volume of discount.

async function handleCancelIntent(env: Env, userId: string, reason: string): Promise<{ action: string }> {
  const stripe = new Stripe(env.STRIPE_SECRET_KEY, { apiVersion: "2025-09-30.clover" });
  const usage = await getRecentUsage(env, userId, 30);
 
  if (reason === "not_using" && usage.taskCount < 5) {
    const subId = await getSubId(env, userId);
    await stripe.subscriptions.update(subId, {
      pause_collection: {
        behavior: "void",
        resumes_at: Math.floor(Date.now() / 1000) + 30 * 86400,
      },
    });
    return { action: "paused_for_30_days" };
  }
  if (reason === "too_expensive") {
    const subId = await getSubId(env, userId);
    await stripe.subscriptions.update(subId, { coupon: "RETENTION_30PCT_60D" });
    return { action: "discount_30pct_60d" };
  }
  return { action: "cancel_proceed" };
}

For "not using" — offer a pause, not a discount. Discounting an already-disengaged user just delays their exit while erasing margin. For "too expensive" — a moderate discount (30% for 60 days) is enough; bigger windows make existing payers feel cheated when they hear about it.

Common Mistakes in Multi-Agent SaaS

1. Agent calls fan out and concurrency explodes. When the orchestrator dispatches to specialists in parallel, a busy hour can multiply calls past your provider's rate limit. Wrap fan-out with a concurrency limiter (e.g., p-limit) capped around 5 — far better than letting Promise.all go wild.

2. Internal logs leak into user-visible output. Showing the agent's "thinking trace" to the user makes the product look unstable when one specialist is uncertain. Show finals only, log internals separately.

3. Plan change double-counts usage. If a user upgrades Standard → Plus mid-month, applying Plus's higher limit while keeping Standard's accumulated count makes early-month usage charged twice. On plan change, don't reset the count, but overwrite the limits. That's the rule that keeps users feeling fairly treated.

Closing — Multi-Agent Should Be Designed as Ongoing Work

Recurring revenue with multi-agent comes less from "wow" features and more from becoming part of someone's monthly workflow. The four-pillar design here — three-layer split, idempotent queues, hybrid pricing, retention flow — all lean toward making the product feel reliable enough to outlast a quarter.

The implementation order that's worked for me: ship an MVP with the orchestrator and one specialist only, wire up Stripe subscriptions, and run the watchdog manually for the first ten paying users. Add the watchdog layer and the third specialist after you have signal on retention, not before — otherwise you over-design for users who won't show up.

If you want to extend the parallelism mindset itself into freelance work, the companion piece Multiplying Your Effective Hourly Rate 10× with Antigravity Multi-Agent shows how the same parallel patterns apply to client services.

Your first 30 minutes should be spent answering one question: "What daily-or-weekly recurring task does my user already do, and would they pay $29/month for an agent team to do quietly in the background?" That answer is the seed of your multi-agent SaaS.

Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Agents & Manager2026-03-18
Building a SaaS Payment System with Stripe × Antigravity — Full-Stack Implementation from Planning to Production
Complete guide to implementing subscription-based SaaS with Stripe and Antigravity. Covers payment flows, webhook handling, subscription lifecycle management, tax calculation, and production deployment strategies.
Agents & Manager2026-05-05
Building a Subscription AI Agent Service with AgentKit 2.0 — Stripe Billing to Monthly Revenue Design
Complete guide to building and monetizing a subscription-based AI agent service using AgentKit 2.0. Covers Stripe integration, multi-agent design, pricing strategy, and churn prevention — everything needed to reach stable monthly recurring revenue.
Agents & Manager2026-05-03
Building an Agent-Driven SaaS on Antigravity and Stripe — A Complete 2026 Implementation Guide
An end-to-end implementation guide for shipping an automation SaaS built on Antigravity's agent capabilities, Stripe, and Cloudflare Workers — covering task queuing, concurrency control, webhook handling, and the agent-specific edge cases (timeouts, partial failure, cost runaway) that always show up.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →