How do you ship 3 AI agents to a marketplace without deploying 3 services?
I built 3 mental-health analysis agents for the aitopia.ai AI App Store:
- CBT Thought Analyzer — detects 11 cognitive distortions (catastrophizing, all-or-nothing, overgeneralization, mind reading, fortune telling, should statements, labeling, personalization, etc.)
- Procrastination Pattern Detector — detects 8 procrastination patterns (perfectionism block, fear of failure, task overwhelm, waiting for motivation, task avoidance, all-or-nothing approach, guilt-procrastination cycle, minimization trap)
- Attachment Style Detector — classifies attachment into Bartholomew's 4-type model (Secure, Preoccupied, Fearful, Dismissing)
All 3 are rule-based (keyword pattern matching, no ML, no LLM, no model needed). And all 3 run on one FastAPI service.
The Architecture
aitopia.ai marketplace
|
+-------------+-------------+
| | |
POST /analyze POST /procrastination POST /attachment
| | |
+-------------+-------------+
|
One FastAPI app
(Render, free tier)
|
+-----------+-----------+
| | |
analyze() procrastination() attachment()
| | |
distortion pattern attachment
detector detector detector
One service. Three routes. Three detectors. Zero duplicated infrastructure.
Why One Service, Not Three
The naive approach is 3 separate deployments. I considered it. Here is why I did not.
1. YAGNI on infrastructure. The 3 detectors share the same stack: FastAPI + Python + the same response envelope. Spinning up 3 Render services triples the deploy surface, triples the cold-start problem (Render free tier spins down after 15 min idle), and triples the monitoring — for zero benefit.
2. Single deploy, single source of truth. When I fix a bug in the shared response formatting or add CORS headers, I push once. Three services means three deploys, three chances to drift, three places to forget the fix.
3. The marketplace does not care. aitopia.ai's remote_http agent type takes an endpointUrl per agent. I registered:
- Agent 1 ->
https://cbt-thought-analyzer.onrender.com/analyze - Agent 2 ->
https://cbt-thought-analyzer.onrender.com/procrastination - Agent 3 ->
https://cbt-thought-analyzer.onrender.com/attachment
The marketplace calls each URL independently. From their side, it looks like 3 services. From my side, it is 1 service with 3 routes. The abstraction holds at the boundary.
The Code Structure
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI(title="CBT Analyzers", version="1.2.0")
class AnalyzeRequest(BaseModel):
text: str
# Route 1: CBT Thought Analyzer (11 distortions)
@app.post("/analyze")
async def analyze_thought(req: AnalyzeRequest):
distortions = detect_distortions(req.text)
return {"detected": distortions, "count": len(distortions)}
# Route 2: Procrastination Pattern Detector (8 patterns)
@app.post("/procrastination")
async def analyze_procrastination(req: AnalyzeRequest):
patterns = detect_procrastination_patterns(req.text)
return {"detected": patterns, "count": len(patterns)}
# Route 3: Attachment Style Detector (4 types)
@app.post("/attachment")
async def analyze_attachment(req: AnalyzeRequest):
style = classify_attachment(req.text)
return {"style": style.type, "dimensions": style.dimensions}
Each detector is a pure function. No shared mutable state. No route depends on another route. If one detector has a bug, the other two routes still work.
The Pricing Model
All 3 agents use aitopia.ai's BYOM (Bring Your Own Model) pricing with fixedCreditsPerRun: 5. Since the detectors are rule-based (no LLM call, no API cost per invocation), the margin is 100% of the credit share. The marketplace takes 30%, I keep 70% of every paid run.
This is the interesting part: rule-based agents on a credit-based marketplace have a structural cost advantage. An LLM-backed agent has to pass the LLM inference cost through every run. My agents cost $0.00 per invocation — the keyword matching is pure CPU. Every credit earned is net positive.
What I Would Do Differently
Version the routes. I went with
/analyze,/procrastination,/attachment. In hindsight,/v1/analyzeetc. would let me ship breaking changes to one agent without touching the others' URLs. Right now a breaking change to the response schema breaks all 3 agents at once.Shared response envelope from day 1. I ended up with 3 slightly different response shapes. A consistent shape would have made client-side rendering cleaner.
Health check per route, not just root. I have
GET /healthat the root. If the/procrastinationroute breaks but/analyzeworks, the root health check still passes. Per-route health checks would let the marketplace detect partial failures.
The Honest Status
All 3 agents are in review on aitopia.ai (submitted ~89 hours ago, no reviewer assigned yet). The endpoints are live and verified — the marketplace's endpointHealth validation passed for all 3. But until an admin approves them, they are not callable by users and earn 0 credits.
The architecture is done. The code is deployed. The gate is external.
Takeaways
- One service, many routes beats many services when the detectors share a stack and you are on a free tier.
- Rule-based agents have a structural cost advantage on credit marketplaces — $0.00 per invocation means every credit is profit.
-
The
remote_httpagent type lets you keep your code on your own infrastructure. You register a URL, the marketplace proxies calls to it. You keep control of the logic. - The hard part is not the code. It is the review queue. I shipped 3 agents in an afternoon. I have been waiting for review for 3+ days.
If you are building agents for a marketplace, consider whether you actually need 3 deployments or just 3 routes on 1. The answer was 1 for me.
The CBT Thought Analyzer is live on GitHub (2 stars, 157 cloners). The FastAPI service is deployed on Render. The agents are pending review on aitopia.ai.
Top comments (0)