The problem
Different teams in the company needed AI assistance for their own workflows — support, operations, and internal tooling all wanted "an agent that understands our area." Building a separate app per team wasn't sustainable: it meant duplicated auth, duplicated UI, and duplicated integration work every time someone needed a new agent.
We built a single platform instead: each specialized agent exposes the same simple conversational interface, where the user just describes their task. Underneath, an n8n workflow orchestrates the actual execution, connecting to the AI models and tools each agent needs.
Role and impact
- Team project, full-stack.
- Unified conversational interface for multiple specialized agents under one platform.
- Feature-based architecture that lets new agents/areas be added without touching unrelated modules.
- Role-based access control (RBAC) so each team only sees and operates the agents relevant to them.
Technical decisions and challenges
As more agents were added for different business areas, a conventional layer-based structure (all components together, all hooks together, etc.) started making it hard to tell which code belonged to which agent, and made it easy to accidentally couple unrelated areas together.
We organized the codebase by feature, with each agent/area owning its own components, hooks, and API access, and layered role-based access control on top so that permissions are enforced consistently at the feature boundary rather than scattered across individual screens. This kept agents isolated from each other and made it straightforward to reason about who can access what.
Each agent needs to call different AI models and different internal/external tools depending on the task it's specialized in. Building and maintaining that orchestration logic directly in the app would have meant redeploying the frontend every time a workflow changed.
We chose to delegate orchestration to n8n workflows, with the platform acting as a thin conversational layer that sends the user's request to the right workflow and streams back the result. This let the team iterate on an agent's underlying logic (which model to call, which tools to chain) without touching the application code, at the cost of the platform needing a clear, versioned contract with each workflow.
Detailed stack
| Layer | Technology | Why |
|---|---|---|
| Frontend | Next.js, shadcn/ui, React Query | Fast conversational UI with consistent components and data fetching |
| Validation | Zod | Type-safe validation of agent requests/responses at the boundary |
| Backend/Auth | Supabase | Auth, database, and role-based access control |
| Orchestration | n8n | Connects agents to AI models and internal tools without app redeploys |
| Tooling | Biome | Fast linting/formatting across the monorepo |
Gallery


What I would do differently
I would formalize the contract between the platform and each n8n workflow earlier — versioning the expected input/output shape per agent from the start would have avoided a few breaking changes as new agents were added.
