Skip to content
cm.
Back to experience
Professional work · Dara ServicesSmall early-user rollout

Dara agency platform.

A multi-tenant platform with shared business modules and configurable AI agents.

TypeScriptNestJSReactModular monolithAI agentsAccess control
Selected architecture and implementation decisions

The product and its constraints

Dara's earlier platform was built for the company's own operations. Its roles, integrations, and commerce workflows assumed a single business. The new product would let independent agencies subscribe to business modules and manage their own organizations. That required rethinking the domain, authentication, and data boundaries.

I designed the application architecture and worked across the NestJS backend and React frontend. With a shrinking team, a limited infrastructure budget, and pressure to ship an MVP, I prioritized simpler deployment and shared code. The existing business assumptions made adapting the old system less practical than starting a new product.

My role

  • Built business modules, organization-scoped permissions, and agent interfaces with tools, document retrieval, external MCP connections, and usage tracking.
  • Set up self-hosted deployment and CI/CD. Moved image builds to GitHub Actions to avoid competing with the running application for server resources.

Engineering decisions

01

Keep module boundaries without separate services

The earlier microservices added communication and deployment overhead. I chose a modular monolith so a smaller team could operate one backend. Modules owned their data and interacted through contracts, dependency injection, or events. The trade-off was enforcing those boundaries inside a shared codebase. Reviews caught cross-module dependencies, including AI-generated ones, that needed refactoring. I used explicit development rules and code review to keep one module from reaching directly into another's repositories.

02

Share contracts and client logic across applications

I organized the API, web, and mobile applications in a Turborepo monorepo. Shared Zod schemas supplied validation and types; shared services and hooks handled API calls and client logic. The web used these packages first, and the mobile administration app reused them as development began. This reduced duplicated logic and made corrections reusable. TypeScript caught incompatible type changes, while shared runtime validation kept constraints consistent. Keeping the code together also gave coding agents context across application boundaries.

03

Run agent tools through existing business services

Agents helped users query several modules without navigating each screen. During early use, a flight-business user asked for upcoming flights and records awaiting payment confirmation. Tools reused the same services as the ordinary interface. Each tool could run directly, request approval, or be disabled. Approval allowed the tool to execute; the backend still checked the acting user's permissions. If that user lacked permission, the operation failed and the agent received the error. This kept business authorization in the backend while letting users control which actions an agent could attempt.

04

Support a smaller, tested set of models

Offering more models also meant supporting differences in tool-calling capabilities, provider requirements, cost, and behavior. I narrowed the list to models I had manually tested with the agents, using public comparisons to help select candidates. This made compatibility easier to check with the time available. Those were practical manual checks, not a formal quality-evaluation system. Supporting another model meant checking it before enabling it.

Early use and what I would simplify

The platform had roughly three months of production use before I left, with a small group of early customers and direct onboarding. Flights saw real use; operations and interactive agents had limited adoption. Recurring agents remained experimental and were tested internally.

I would start with a narrower MVP. Configurable permission conditions anticipated future needs but took substantial effort to implement and verify, while few were used. I would keep entity-and-action permissions and add conditional rules as concrete workflows required them. Faster implementation with AI did not remove the need to validate demand or limit complexity.

Back to experience