Controla.Club
Club management SaaS with an agent that can touch real data.

Founder-engineer · architecture, AI, infra
Members, billing, access control and training for sports clubs, academies and gyms. Clubs used to chase payments on WhatsApp and check receipts by hand; the platform does both, and Controli, its assistant, answers questions and acts on the club’s data.
- commits
- 2,469
- commits
- test files
- 628
- test files
- AWS services
- 16
- AWS services
- Next.js 16
- LangGraph
- pgvector
- Supabase
- AWS Lambda
- SQS
- SST
- OpenRouter
- MCP
- Baileys
- C# .NET
What I built
- Controli: a LangGraph supervisor that routes each turn, by forced tool call, to one of six specialists. It holds no domain tools itself.
- Hybrid RAG: Spanish full-text search plus pgvector, fused with Reciprocal Rank Fusion, degrading to lexical search when embeddings fail.
- Payment AI: a WhatsApp receipt goes through receiver → SQS → worker; a graph classifies it, reads the amount, matches pending charges and stops for human approval.
- Club Radar: deterministic snapshot → churn scoring → analyze, critique, investigate with sandboxed SQL, synthesize. Validated with zod, capped by a per-club monthly AI budget.
- An MCP server that exposes club, CRM and news tools behind scoped tokens.
The hard parts
Text-to-SQL that cannot escape
The agent runs SQL under a read-only Postgres role, behind a lexer faithful to Postgres that closes role-escape and SECURITY DEFINER gaps. Both have their own test suites.
Policy from the server, never from the model
Tool calls are authorised against server context with an allowlist. Risk grows with the real scope of the input: deleting one member is not deleting four hundred. Risky actions need a typed confirmation.
Guards born from incidents
After the model invented a URL in production, a link guard checks and strips any controla.club link that does not exist. A verifier removes internal citation markers before the answer leaves.



