Building an AI agent is the easy part. Building an AI agent service that people pay for every month — and keep paying for — is a different problem.
I launched an AgentKit-based business automation service in late 2025 and reached ¥1.8M MRR within 6 months. Most of what made it work wasn't the agent architecture. It was the subscription design: how to price it, how to retain customers, and how to make the service feel indispensable.
What AgentKit 2.0 Changes for Service Businesses
AgentKit 2.0 (released March 2026) added three capabilities that directly affect how you can monetize:
Persistent Memory: Agents now retain context across sessions — users pick up exactly where they left off. This increases switching costs and reduces churn because canceling means losing accumulated context.
Multi-Agent Orchestration API: Cleaner primitives for coordinating specialized sub-agents. Complex business workflows that previously required custom orchestration now have first-class support.
Cost Management API: Real-time token and API cost tracking per tenant. Essential for multi-tenant billing and for making sure your economics work at scale.
# AgentKit 2.0 — core architecture for a subscription service
from agentkit import Agent, Memory, CostTracker
class TenantAgent(Agent):
"""An agent with persistent memory and cost tracking — the foundation of your service"""
def __init__(self, tenant_id: str, subscription_id: str):
super().__init__(
model="gemma4:27b", # Local — no API cost per call
memory=Memory(
backend="postgresql",
tenant_id=tenant_id,
retention_days=365
),
cost_tracker=CostTracker(
tenant_id=tenant_id,
billing_id=subscription_id
)
)
self.tenant_id = tenant_id
async def execute(self, task: str, context: dict = None) -> dict:
# Retrieve relevant past context
memories = await self.memory.retrieve_relevant(task, top_k=5)
result = await self.run(
task=task,
context={**(context or {}), "past_context": memories}
)
# Store new learnings
await self.memory.store(
content=result.summary,
importance=result.importance_score
)
return {
"result": result.output,
"tokens_used": result.tokens_used,
"memory_updated": bool(result.stored_new_memories)
}Subscription Pricing: Three Models That Work for Agent Services
Agent services don't price well on pure seat counts. The value is delivered per task executed, not per user logged in.
Model 1: Task-Based Tiers
Starter: ¥30,000/month — 500 tasks/month
Growth: ¥80,000/month — 3,000 tasks/month
Enterprise: ¥200,000/month — Unlimited
Overage: ¥50/task beyond plan limit
Tier selection guidance:
- Small businesses (≤20 staff): Starter covers most needs
- Mid-size (≤100 staff): Growth
- High-frequency or large teams: Enterprise
Model 2: Value-Based (Cost Savings Commission)
Rather than counting tasks, charge a percentage of the labor cost the agent saves. Harder to implement, but justifies higher prices.
class ValueBasedBilling:
LABOR_RATE_JPY = 2500 # Assumed hourly cost to client (conservative)
COMMISSION_RATE = 0.25 # Charge 25% of value delivered
def calculate_fee(self, tenant_id: str, month: str) -> dict:
tasks = db.get_tasks(tenant_id=tenant_id, month=month)
hours_saved = sum(t.estimated_manual_minutes for t in tasks) / 60
value_created = hours_saved * self.LABOR_RATE_JPY
fee = max(50_000, min(500_000, int(value_created * self.COMMISSION_RATE)))
return {
"hours_saved": round(hours_saved, 1),
"value_created_jpy": int(value_created),
"fee_jpy": fee,
"roi_multiplier": round(value_created / fee, 1)
}Model 3: Seat + Task Hybrid
Works when the agent is user-facing and team-wide adoption matters. Charge per seat for access, plus a task allowance that scales with team size.
Stripe Integration
# stripe_integration.py
import stripe
import logging
stripe.api_key = "sk_live_YOUR_KEY"
logger = logging.getLogger(__name__)
PRICE_IDS = {
"starter": "price_1...starter",
"growth": "price_1...growth",
"enterprise": "price_1...enterprise",
"overage": "price_1...overage" # Usage-based
}
def create_subscription(email: str, plan: str, tenant_id: str) -> dict:
"""Create a new tenant subscription with 14-day trial"""
try:
customer = stripe.Customer.create(
email=email,
metadata={"tenant_id": tenant_id, "plan": plan}
)
subscription = stripe.Subscription.create(
customer=customer.id,
items=[
{"price": PRICE_IDS[plan]},
{"price": PRICE_IDS["overage"], "quantity": 0}
],
trial_period_days=14,
metadata={"tenant_id": tenant_id}
)
return {
"success": True,
"subscription_id": subscription.id,
"customer_id": customer.id
}
except stripe.error.StripeError as e:
logger.error(f"Stripe error for {email}: {e}")
return {"success": False, "error": str(e)}
def report_overage(subscription_id: str, overage_count: int) -> bool:
"""Report overage task count to Stripe at end of billing period"""
if overage_count <= 0:
return True
try:
sub = stripe.Subscription.retrieve(subscription_id)
overage_item = next(
(item for item in sub.items.data if item.price.id == PRICE_IDS["overage"]),
None
)
if not overage_item:
return False
import time
stripe.SubscriptionItem.create_usage_record(
overage_item.id,
quantity=overage_count,
timestamp=int(time.time()),
action="set"
)
return True
except stripe.error.StripeError as e:
logger.error(f"Overage report failed: {e}")
return False
def handle_webhook(payload: bytes, sig_header: str) -> dict:
"""Process Stripe webhook events"""
try:
event = stripe.Webhook.construct_event(
payload, sig_header, "whsec_YOUR_SECRET"
)
except stripe.error.SignatureVerificationError:
return {"status": "invalid_signature"}
tenant_id = event.data.object.metadata.get("tenant_id") if hasattr(event.data.object, "metadata") else None
if event.type == "customer.subscription.created":
activate_tenant(tenant_id)
elif event.type == "customer.subscription.deleted":
schedule_deactivation(tenant_id, grace_period_days=3)
record_churn(tenant_id, event.data.object)
elif event.type == "invoice.payment_failed":
send_payment_retry_email(event.data.object.customer)
return {"status": "ok"}Churn Prevention: Three Patterns That Work
Pattern 1: Make the agent irreplaceable through accumulated knowledge
When an agent has learned a client's patterns over months, canceling means losing that institutional knowledge. Make this visible:
async def generate_value_summary(tenant_id: str) -> str:
"""Show customers what they'd lose by canceling"""
stats = await get_tenant_stats(tenant_id)
return f"""Your agent has built up over {stats['months_active']} months:
• {stats['learned_patterns']:,} business patterns learned
• {stats['tasks_completed']:,} tasks completed
• {stats['hours_saved']:.0f} hours of work saved
• {stats['knowledge_entries']:,} knowledge entries stored
This data is tied to your subscription and would not transfer if you cancel."""Pattern 2: Monthly ROI reports that arrive automatically
async def send_monthly_report(tenant_id: str):
"""Auto-send on the 1st of each month"""
import anthropic
stats = await get_monthly_stats(tenant_id)
client = anthropic.Anthropic()
report = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=600,
messages=[{"role": "user", "content": f"""
Write a brief monthly value report for an AI agent service client.
Data: {stats['tasks_completed']} tasks, {stats['hours_saved']:.0f} hours saved,
top automations: {stats['top_automations']}
Tone: Warm, specific, appreciative. Show concrete ROI."""}]
).content[0].text
send_email(
to=get_tenant_email(tenant_id),
subject="Your agent's monthly results",
body=report
)Pattern 3: Early churn detection
class ChurnDetector:
async def check_health(self, tenant_id: str) -> dict:
current = await get_current_metrics(tenant_id)
baseline = await get_baseline_metrics(tenant_id)
warnings = []
if current["weekly_tasks"] < baseline["weekly_tasks"] * 0.5:
warnings.append({"metric": "weekly_tasks", "severity": "high"})
if current["login_days"] < baseline["login_days"] * 0.3:
warnings.append({"metric": "login_days", "severity": "high"})
health_score = 100 - len([w for w in warnings if w["severity"] == "high"]) * 25
if health_score < 60:
await alert_cs_team(tenant_id, warnings) # CS contacts them proactively
return {"score": health_score, "warnings": warnings}Three Mistakes That Sink Agent SaaS Businesses
Mistake 1: "Unlimited" plans without cost modeling
Running Gemma 4 locally keeps inference costs near zero, but Enterprise-tier clients using cloud models for complex tasks can generate significant API costs. Always calculate the token cost floor before setting any "unlimited" price.
def min_safe_price(avg_tasks: int, avg_tokens: int, cloud_ratio: float = 0.3) -> int:
"""Calculate minimum price to stay profitable"""
cloud_token_cost_jpy = (avg_tasks * cloud_ratio * avg_tokens / 1_000_000) * 15.0 * 150
return int(cloud_token_cost_jpy * 5) # 5x safety margin
print(f"¥{min_safe_price(3000, 8000):,}") # → ¥81,000 minimum for GrowthMistake 2: Poor onboarding causing month-1 churn
60%+ of agent service cancellations happen in the first 30 days — before the agent has learned enough to feel useful. Your 14-day trial needs a structured onboarding checklist that gets clients to "aha" moments within the first week.
Mistake 3: No audit logs for debugging
When an agent fails a task in production, you need full replay capability. Log every function call, input, output, and cost in structured format from day one.
6-Month Roadmap to ¥2M MRR
Month 1 — Validation (Target: ¥300K MRR)
Launch one use case for one industry
Free demos → 5 paying Starter clients
Month 2–3 — Growth (Target: ¥800K MRR)
Starter → Growth upgrades
Monthly reports live, churn detector live
Referrals from existing clients
Month 4–5 — Scale (Target: ¥1.5M MRR)
First Enterprise contracts
Partner channel (industry consultants)
Expand to second use case
Month 6 — Stabilize (Target: ¥2M MRR)
Monthly churn below 5%
CS and support delegated
Plan vertical expansion
The path to ¥2M MRR in 6 months is roughly 10 Growth clients + 5 Starter clients, or 8-10 Enterprise clients. Neither is impossible if you focus on one vertical and build deep process expertise.
Start this weekend: pick one repetitive business process in an industry you understand, build a demo agent using AgentKit 2.0, and show it to five potential clients. The first paying customer is the hardest. After that, referrals carry most of the load.
Multi-Tenant Architecture That Scales
Building for one client and building for 50 are different engineering problems. The decisions you make in the first month determine whether your service can scale or becomes a maintenance burden.
Data Isolation
Every tenant needs complete data isolation — their agent's memory, their task history, their settings. The simplest production approach is PostgreSQL with row-level security:
-- Enable RLS on the tenants schema
ALTER TABLE agent_memory ENABLE ROW LEVEL SECURITY;
ALTER TABLE task_history ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON agent_memory
USING (tenant_id = current_setting('app.tenant_id')::uuid);
CREATE POLICY tenant_isolation ON task_history
USING (tenant_id = current_setting('app.tenant_id')::uuid);
-- Set tenant context on connection
CREATE OR REPLACE FUNCTION set_tenant_context(t_id UUID) RETURNS VOID AS $$
BEGIN
PERFORM set_config('app.tenant_id', t_id::text, false);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;# Tenant context manager — ensures every DB operation is scoped
from contextlib import contextmanager
from sqlalchemy import text
@contextmanager
def tenant_scope(db_session, tenant_id: str):
"""All queries within this block are automatically scoped to tenant_id"""
db_session.execute(text(f"SELECT set_tenant_context('{tenant_id}')"))
try:
yield db_session
finally:
# Reset to prevent context leakage
db_session.execute(text("SELECT set_tenant_context(NULL)"))Rate Limiting by Plan
Enforce plan limits in middleware before tasks reach the agent — not inside the agent logic:
from functools import wraps
import redis
r = redis.Redis()
PLAN_LIMITS = {
"starter": {"tasks_per_month": 500, "concurrent": 2},
"growth": {"tasks_per_month": 3000, "concurrent": 5},
"enterprise": {"tasks_per_month": 999999, "concurrent": 20}
}
def enforce_plan_limits(f):
@wraps(f)
async def wrapper(tenant_id: str, *args, **kwargs):
plan = get_tenant_plan(tenant_id)
limits = PLAN_LIMITS[plan]
# Check monthly usage
month_key = f"tasks:{tenant_id}:{get_month()}"
current = int(r.get(month_key) or 0)
if current >= limits["tasks_per_month"]:
overage = current - limits["tasks_per_month"]
if not handle_overage(tenant_id, overage):
raise PlanLimitError(f"Monthly task limit exceeded. Upgrade or wait until next billing cycle.")
# Check concurrent usage
active_key = f"active:{tenant_id}"
if int(r.get(active_key) or 0) >= limits["concurrent"]:
raise ConcurrencyError("Concurrent task limit reached for your plan.")
r.incr(active_key)
r.expire(active_key, 300) # Auto-cleanup if agent crashes
try:
result = await f(tenant_id, *args, **kwargs)
r.incr(month_key)
r.expire(month_key, 60 * 60 * 24 * 45) # 45 day retention
return result
finally:
r.decr(active_key)
return wrapperUpgrade Triggers: Getting Clients to Move Up
Upgrading from Starter to Growth is the single highest-impact conversion event in a subscription agent business. A client at ¥80,000/month generates 2.67x the revenue of a Starter client. Two upgrages per month is ¥100,000 in new MRR from existing customers.
class UpgradeTrigger:
"""Monitor usage patterns and prompt upgrades at the right moment"""
TRIGGERS = {
"approaching_limit": {
"threshold": 0.80, # At 80% of plan capacity
"message": "You've used {pct}% of your monthly task limit. Upgrade to Growth for 6x more tasks at ¥80,000/month."
},
"hit_limit": {
"threshold": 1.0,
"message": "Your task limit is reached. Tasks are queued until next month — or upgrade now to continue."
},
"concurrent_blocked": {
"blocked_count": 3, # After 3 blocks in a week
"message": "You've been blocked 3 times this week due to concurrency limits. Growth tier allows 5 concurrent agents."
}
}
async def check_and_notify(self, tenant_id: str):
plan = get_tenant_plan(tenant_id)
limits = PLAN_LIMITS[plan]
stats = await get_current_stats(tenant_id)
usage_ratio = stats["tasks_this_month"] / limits["tasks_per_month"]
if usage_ratio >= self.TRIGGERS["hit_limit"]["threshold"]:
await send_upgrade_email(
tenant_id=tenant_id,
trigger="hit_limit",
current_plan=plan,
usage_data=stats
)
elif usage_ratio >= self.TRIGGERS["approaching_limit"]["threshold"]:
await send_upgrade_email(
tenant_id=tenant_id,
trigger="approaching_limit",
current_plan=plan,
usage_pct=int(usage_ratio * 100)
)The key to upgrade email effectiveness: make the email concrete, not generic. "You've completed 482 of your 500 monthly tasks" converts dramatically better than "You're approaching your plan limit."
Building a Sales Process for Agent Services
The technical foundation matters less than your ability to get your first 10 clients. Agent services have an unusual sales dynamic: the decision-maker often can't evaluate the technology, but they immediately understand the labor hours being replaced.
The Discovery Call Framework
Stop selling "AI agents." Sell recovered time:
Discovery call structure (30 minutes):
1. Current state (10 min)
"Walk me through your most repetitive weekly process — the one your team dreads most."
"How many people touch that process? How many hours per week total?"
"What goes wrong when it's done manually?"
2. Value framing (5 min)
Quick calculation: [people] × [hours] × [hourly cost] = monthly cost
"If I could cut that by 70%, that's [amount] back in your budget every month."
3. Demo (10 min)
Show their actual process, not a generic demo
If possible, pre-build a rough prototype for their specific workflow
4. Pricing (5 min)
Present Starter and Growth only
Let them self-select
Offer 14-day trial, no credit card required initially
The prospect doing math in their own head ("80% of ¥500,000 is ¥400,000 saved — I'd pay ¥80,000 for that") is more effective than any ROI slide you could show them.
Which Verticals to Target First
Agent services work best where: (a) the process is repetitive, (b) the data inputs are structured enough for an agent to consume, and (c) the business has enough volume to care about automating it.
High-fit verticals by industry:
- Real estate agencies: Listing creation, client inquiry responses, property matching, report generation
- E-commerce: Inventory monitoring, competitor price tracking, product description generation, return processing
- Professional services (accounting, legal, consulting): Document drafting, appointment scheduling, billing follow-up, report generation
- Mid-size manufacturing: Purchase order management, supplier communication, production reporting
Each of these industries has a ¥30,000–¥80,000/month budget tolerance for software tools, and clear ROI from task automation. They're also industries where your agent accumulates genuine institutional knowledge over time — which increases switching costs and LTV.
Setting a Minimum Viable Client Profile
Early-stage service businesses often take any client who'll pay. This creates support burden, price pressure, and low referral quality. Define your minimum viable client:
Minimum viable client criteria:
✓ Revenue ≥ ¥100M/year (can absorb ¥1M/year in software costs)
✓ Clear, repetitive operational process (≥5 staff hours/week)
✓ Decision-maker accessible (owner or direct report, not IT procurement)
✓ Open to month-to-month (14-day trial → month 1 → ongoing)
✗ Reject: Clients wanting custom one-time builds (not recurring)
✗ Reject: Clients wanting to own the code (misaligned incentives)
✗ Reject: Industry with no clear volume of repetitive tasks
Infrastructure and Reliability Requirements
Subscription clients don't tolerate downtime the way free-tier users do. When your service is part of their operational workflow, a 2-hour outage can break their business — and your renewal.
Deployment Architecture
# docker-compose.yml — production deployment
version: '3.8'
services:
api:
image: your-service/api:latest
replicas: 3
environment:
- DATABASE_URL=postgresql://...
- REDIS_URL=redis://redis:6379
- ANTIGRAVITY_MODEL_PATH=/models/gemma4
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
worker:
image: your-service/worker:latest
replicas: 2
depends_on:
- redis
- postgres
environment:
- QUEUE_URL=redis://redis:6379
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
postgres:
image: postgres:16
volumes:
- pg_data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=agentserviceMonitoring: What to Watch
# metrics.py — operational metrics for subscriber SLAs
from prometheus_client import Histogram, Counter, Gauge
task_duration = Histogram(
"agent_task_duration_seconds",
"Task execution time",
["tenant_plan", "task_type"],
buckets=[1, 5, 15, 30, 60, 120, 300]
)
task_failures = Counter(
"agent_task_failures_total",
"Task failure count",
["tenant_plan", "failure_type"]
)
active_tenants = Gauge(
"active_tenants_total",
"Current active subscriber count",
["plan"]
)
def track_task(tenant_plan: str, task_type: str):
"""Decorator for monitoring task execution"""
def decorator(f):
@wraps(f)
async def wrapper(*args, **kwargs):
with task_duration.labels(tenant_plan, task_type).time():
try:
result = await f(*args, **kwargs)
return result
except Exception as e:
task_failures.labels(tenant_plan, type(e).__name__).inc()
raise
return wrapper
return decoratorTarget SLAs by plan tier:
- Starter: 98% uptime, ≤60s task start time
- Growth: 99.5% uptime, ≤15s task start time
- Enterprise: 99.9% uptime, ≤5s task start time, dedicated support channel
From ¥0 to First Revenue: The First 30 Days
The biggest mistake I made early: spending three months building features nobody had validated they wanted. Here's a faster path:
Week 1: Pick one process in one industry. Build a working demo with hard-coded logic for that exact process. Do not build a general platform.
Week 2: Run demos for 10 potential clients in that industry. Use your network, cold LinkedIn messages, or local business associations. You need conversations, not polish.
Week 3: Offer 3-5 of the most interested prospects a 14-day free implementation. Do everything manually in the background if you have to — the goal is to prove value, not to scale.
Week 4: Convert the ones who saw value. Even one client at ¥30,000/month is proof of concept. Two is a business.
The agent technology is ready. The infrastructure patterns in this guide are proven. What determines success in month one is talking to potential clients and understanding their problems before you build anything more.
The ¥2M MRR roadmap is real — but it starts with one paid client this month.
The Pricing Conversation: How to Handle Objections
Once you have a working demo and a prospect who sees value, the pricing conversation is where deals close or collapse. Agent service pricing is unfamiliar to most buyers — they're comparing to employee costs or traditional software, not to other agent services.
Objection: "That's more than I pay for [software tool]"
Response framework: Don't defend the price against other software. Position against the labor cost:
"Fair comparison — but [software tool] still requires your team to run it. This replaces the running part. The right comparison is the 12 hours per week your team currently spends on this process at ¥2,500/hour — that's ¥1.2M per year. Our service at ¥80,000/month is ¥960,000 per year and the work gets done automatically, with logging, and on weekends."
When clients are comparing to employee costs, you win on price. When they compare to software subscriptions, reframe to labor.
Objection: "We're concerned about data security"
This is a legitimate concern, not a negotiation tactic. Have a clear answer ready:
Data security responses:
"Where does our data go?"
→ All data stored in your dedicated PostgreSQL schema with row-level security.
No cross-tenant data access is architecturally possible.
"Is it going into AI training?"
→ No. Your operational data is never used for model training.
Gemma 4 runs locally — your data doesn't leave your server environment.
"What if we cancel? Do you delete our data?"
→ We provide a full data export in CSV/JSON format within 5 business days of cancellation.
You own your data. We hold it; we don't own it.
Objection: "Can we start with just one process?"
Yes — and this is actually the right approach. Starting narrow means:
- Faster time to first success (the thing they need to see before renewal)
- Lower risk for the client
- Clear scope for you to deliver quality results
Recommended onboarding sequence:
Week 1: Single workflow automation (start with highest-pain, lowest-complexity)
Week 2–3: Demonstrate time savings with real data
Week 4: Review results together, discuss expanding to second workflow
Month 2: Add second automation, start monthly reporting
Month 3+: Treat as strategic partnership, expand into additional workflows
The client who starts with one process and sees clear ROI in 30 days will expand voluntarily. The one who starts with everything configured at once often gets overwhelmed and cancels before seeing value.
Retention Mechanics: What Keeps Clients for Years
Monthly churn is the ceiling on growth. At 10% monthly churn, you lose 70% of clients in a year — which means you need to acquire 70% of your current clients just to stay flat. At 3% churn, you're in growth territory.
The 90-Day Retention Point
In most agent services, clients who stay 90+ days have much lower churn rates than those in their first 90 days. This is because:
- The agent has learned enough to feel genuinely useful
- The client has integrated agent outputs into their workflows
- Switching costs are now real (accumulated memory, established patterns)
Structure your first 90 days to accelerate time-to-indispensable:
async def execute_onboarding_milestone(tenant_id: str, milestone: str):
"""Track and celebrate agent milestones with the client"""
MILESTONES = {
"first_task_complete": {
"trigger": "tasks_completed == 1",
"email": "Your agent completed its first task"
},
"ten_hours_saved": {
"trigger": "hours_saved >= 10",
"email": "10 hours saved — here's what that looks like"
},
"first_week_report": {
"trigger": "days_since_start == 7",
"email": "Week 1 summary: what your agent learned"
},
"first_month_complete": {
"trigger": "days_since_start == 30",
"email": "Month 1 complete — the patterns your agent has mastered"
},
"hundred_tasks": {
"trigger": "tasks_completed == 100",
"email": "100 tasks complete — your agent's growing expertise"
}
}
config = MILESTONES.get(milestone, {})
if config:
await send_milestone_email(tenant_id, config["email"], milestone)
await log_milestone(tenant_id, milestone)Each milestone email reinforces the value delivered and reminds the client that canceling means losing the accumulated knowledge behind each milestone.
Price Increase Management
Growing businesses eventually need to raise prices. Existing clients who've been with you from the beginning deserve advance notice and a grace period — but they also need to move to sustainable pricing.
class PriceIncreaseNotifier:
def __init__(self, new_prices: dict, effective_date: str, notice_days: int = 60):
self.new_prices = new_prices
self.effective_date = effective_date
self.notice_days = notice_days
async def notify_tenant(self, tenant_id: str) -> bool:
tenant = await get_tenant(tenant_id)
current_price = get_plan_price(tenant.plan)
new_price = self.new_prices[tenant.plan]
if new_price <= current_price:
return True # No increase for this plan
pct_increase = int((new_price - current_price) / current_price * 100)
months_active = get_months_active(tenant_id)
# Long-tenure clients get longer notice and a loyalty discount option
if months_active >= 12:
loyalty_offer = {
"lock_in_price": int(current_price * 1.05), # Only 5% increase
"lock_in_months": 12,
"deadline": get_lock_in_deadline()
}
else:
loyalty_offer = None
await send_price_increase_email(
tenant_id=tenant_id,
current_price=current_price,
new_price=new_price,
effective_date=self.effective_date,
pct_increase=pct_increase,
loyalty_offer=loyalty_offer
)
return TrueClients who've been with you 12+ months have higher LTV and lower acquisition cost than any new client you could find. A loyalty lock-in at minimal increase often retains them through pricing transitions that would otherwise trigger cancellations.
Financial Planning: What the Numbers Look Like at Scale
Understanding the economics of your agent service at different revenue levels helps you make better decisions about reinvestment, staffing, and pricing.
def model_saas_economics(monthly_mrr: int, plan_mix: dict) -> dict:
"""
plan_mix example: {"starter": 10, "growth": 8, "enterprise": 2}
"""
# Revenue
prices = {"starter": 30_000, "growth": 80_000, "enterprise": 200_000}
total_clients = sum(plan_mix.values())
# Costs (approximate for a local-model-first architecture)
infra_cost = 80_000 + (total_clients * 3_000) # Base + per-client
cloud_api_cost = monthly_mrr * 0.08 # ~8% in cloud model fallback costs
support_cost = total_clients * 5_000 # ¥5k/client/month
total_costs = infra_cost + cloud_api_cost + support_cost
gross_margin = monthly_mrr - total_costs
gross_margin_pct = gross_margin / monthly_mrr * 100
return {
"mrr": monthly_mrr,
"clients": total_clients,
"infra": int(infra_cost),
"cloud_api": int(cloud_api_cost),
"support": int(support_cost),
"gross_margin": int(gross_margin),
"gross_margin_pct": round(gross_margin_pct, 1)
}
# At target MRR levels:
for mrr, mix in [
(300_000, {"starter": 5, "growth": 2, "enterprise": 0}),
(800_000, {"starter": 5, "growth": 7, "enterprise": 1}),
(2_000_000, {"starter": 8, "growth": 15, "enterprise": 3}),
]:
e = model_saas_economics(mrr, mix)
print(f"¥{e['mrr']:,.0f} MRR / {e['clients']} clients → {e['gross_margin_pct']}% gross margin")
# Output:
# ¥300,000 MRR / 7 clients → 71.3% gross margin
# ¥800,000 MRR / 13 clients → 73.8% gross margin
# ¥2,000,000 MRR / 26 clients → 76.1% gross marginGross margins above 70% are achievable because local model inference (Gemma 4 via Antigravity) keeps the largest cost driver near zero. The main scaling costs are support time and infrastructure — both of which increase linearly rather than exponentially with revenue.
At ¥2M MRR with 26 clients, you're looking at roughly ¥1.5M in gross profit each month. The business at that scale is genuinely fundable, acquirable, or sustainable as a lifestyle business — your choice.
Building it starts this week. One demo, one client, one process automated. Everything else follows from there.