Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Ai Agentic Erp Builder

FreeNot checked

Multi-tenant AI Orchestrator platform for SMEs — domain agents (Finance, HR, Sales, Supply, Compliance), multi-channel I/O, RLS-isolated Postgres, pluggable ERP

GitHubEmbed

About

Multi-tenant AI Orchestrator platform for SMEs — domain agents (Finance, HR, Sales, Supply, Compliance), multi-channel I/O, RLS-isolated Postgres, pluggable ERP connectors. Architecture showcase.

README

Multi-tenant AI Orchestrator platform for SMEs — domain agents (Finance, HR, Sales, Supply, Compliance), multi-channel I/O (REST, Web Chat, Telegram, Discord), pluggable ERP connectors, and an admin console for tenant + agent + channel-bot management.

[!IMPORTANT] This is a public showcase repository. It documents the architecture, agent system, and tech stack of a production AI ERP platform built across three internal codebases. Source code lives in private monorepos and is not mirrored here — this repo is the high-level engineering map.

[!NOTE] Last updated: 2026-05-07 · Author: Tran Phong · Stack: NestJS · TypeScript · PostgreSQL 16 (RLS) · Redis 7 · Drizzle ORM · BullMQ · Vercel AI SDK · React 18 · shadcn/ui · Turborepo + pnpm.

Navigation


What it is

An AI Agentic ERP is an ERP/CRM whose primary surface is conversational. Instead of clicking through 200 screens, users talk to domain agents. Each agent has scoped tools (ERP connectors), tenant-isolated memory, and policy-aware prompts.

Built for Vietnamese SMEs that want enterprise capabilities without the enterprise license model — conversational over web/Telegram/Discord, deployable as a SaaS, and pluggable into any existing ERP (Twendee ERP, Odoo, SAP B1) via a connector layer.

flowchart LR
    U1[Web Chat Widget]
    U2[Telegram Bot]
    U3[Discord Bot]
    U4[REST API]

    U1 & U2 & U3 & U4 --> GW[API Gateway<br/>NestJS · JWT · Throttle]
    GW --> ORC[Orchestrator<br/>intent → routing]

    ORC --> A1[Finance Agent]
    ORC --> A2[HR Agent]
    ORC --> A3[Sales Agent]
    ORC --> A4[Supply Agent]
    ORC --> A5[Compliance Agent]

    A1 & A2 & A3 & A4 & A5 --> LLM[LlmPort<br/>Claude · GPT · Gemini]
    A1 & A2 & A3 & A4 & A5 --> ERP[ERP Connectors<br/>Twendee · Odoo · SAP]

    GW -.audit.-> DB[(PostgreSQL 16<br/>RLS · Drizzle)]
    ORC -.queue.-> Q[(Redis 7<br/>BullMQ)]

System architecture

Layered NestJS modular monolith. RLS-enforced tenant isolation at the database level. Agents are dynamic — definitions live in DB and can be customized per tenant without code changes.

Layer Responsibility Key components
Channels Adapt platform-specific protocols to internal chat events Web Widget · Telegram Webhook · Discord Bot · REST /v1/chat
Auth JWT issuance, refresh-token rotation, tenant-scoped guards AuthService, JwtAuthGuard, throttle 5 req/min
Orchestrator Intent classification → agent routing → response assembly OrchestratorService, PromptAssembler (3-layer safety)
Agent framework Pluggable agent contract, dynamic resolution Agent interface, DynamicAgentResolver, AgentRegistry
LLM Multi-provider abstraction with tier routing LlmPort, LlmProviderFactory, token metering
ERP connectors Pluggable adapters to host ERPs @twd/erp-adapters (per-vendor implementations)
Memory Sliding-window context, tenant-scoped conversation history MemoryService, ConversationsService
Persistence RLS-protected Postgres + Redis cache + BullMQ queues Drizzle ORM, ioredis, @aes-encryption/*

3-layer prompt safety

flowchart TB
    SYS[Layer 1: System Prompt<br/>immutable agent contract]
    POL[Layer 2: Tenant Policy<br/>scope guard, allowed actions]
    USR[Layer 3: User Message<br/>untrusted input]
    SYS --> POL --> USR --> LLM[LLM]

User input never bypasses tenant policy. Policy never bypasses agent contract. Each layer is concatenated by PromptAssembler with explicit role separation.


Domain agents

Five seeded agents per tenant. Definitions stored in dynamic_agent_definitions — fully editable from the admin console.

Agent Sample intents Tools / connectors
Finance "Issue payment voucher for invoice #234", "Reconcile bank statement", "Show outstanding receivables > 30 days" GL accounts, payment vouchers, receipts, cash flow report
HR "Approve leave request for Mai", "What's John's leave balance?", "Generate payroll for May 2026" Employees, attendance, contracts, leave balance, payroll sheet
Sales "Create deal for Acme — $50K, stage Qualification", "Move pipeline X to negotiation", "Email sequence to cold leads" Deals, kanban pipeline, lead enrichment (Apollo), email sequences
Supply "PO status for SKU-1090", "Restock alert for low-inventory items", "Vendor performance report" Purchase orders, suppliers, inventory levels
Compliance "Audit who changed customer #112 last 30d", "GDPR export for user X", "Tax filing readiness check" Audit logs, RLS reports, BHXH (VN social insurance) workflows

Each agent ships with scoped tool access. The orchestrator never lets a Sales agent issue a payment voucher.


Channel surfaces

Surface Auth Path Notes
Web chat widget JWT cookie Embeddable <script> tag (Vite lib mode) Streamed responses via SSE
Telegram bot Per-bot encrypted token + secret POST /webhooks/telegram/:botId Path-based routing; idempotency via Redis SETNX on update_id
Discord bot Bot token Webhook + slash commands Same orchestrator backend
REST API Bearer JWT POST /api/v1/chat, POST /api/v1/chat/stream For programmatic integrations

Telegram webhook flow (async, fire-and-forget)

sequenceDiagram
    participant TG as Telegram
    participant API as Webhook /:botId
    participant R as Redis
    participant Q as BullMQ
    participant W as Worker
    participant ORC as Orchestrator
    participant A as Agent

    TG->>API: POST update
    API->>API: Validate bot + secret
    API->>R: SETNX update_id (idempotent)
    alt new
      API->>Q: enqueue job
      API-->>TG: 200 OK
      Q->>W: dequeue
      W->>ORC: process(message)
      ORC->>A: route
      A-->>W: reply
      W->>TG: sendMessage
    else duplicate
      API-->>TG: 200 OK (skip)
    end

200 OK returns immediately — prevents Telegram retry storms when an LLM call takes 4–8s.


Multi-tenancy & isolation

Mechanism Where Purpose
PostgreSQL RLS tenants, users, conversations, agents, channel_bots tables Hard isolation — no app-level bypass
Tenant-scoped JWT tenantId claim, extracted by JwtAuthGuard Every query carries tenant context
AES-encrypted secrets tenant_configs.api_keys, channel_bots.bot_token Per-tenant LLM keys, bot tokens at rest
Per-tenant LLM tier LlmProviderFactory reads tenant tier → routes Claude/GPT/Gemini Enables BYOK and cost segregation
Token metering TokenMeteringService (Redis counters) Quota enforcement + billing input
Team scoping teams + team_agents (M2M) Group agents under a team; channel bots bind to one team

Tech stack

Concern Choice Why
Backend framework NestJS 10 Modular monolith with clean DI, fits agent/orchestrator separation
ORM Drizzle Typed schema + RLS-friendly raw SQL escape hatch
Cache + queue Redis 7 + BullMQ Idempotency keys + async webhook processing
LLM SDK Vercel AI SDK Provider-neutral, streamable, tool-calling friendly
LLM providers Anthropic + OpenAI + Gemini Tier routing per tenant (cost vs quality)
Frontend React 18 + Vite + shadcn/ui Admin console + embeddable chat widget (lib mode)
Monorepo Turborepo + pnpm Build graph (shared-types → apps), workspace deps
Auth JWT + refresh rotation + bcrypt Standard, throttled at 5 req/min on /auth/*
Encryption AES-256-GCM Per-tenant secrets at rest
Container Multi-stage Node 20-alpine Non-root user, ~120MB image

Repo composition

The platform is split across three private codebases. Each owns a clean domain and depends only on the contracts above it.

Codebase Role Stack
Agents Hub (orchestrator core) Multi-tenant agent runtime, channels, admin API NestJS · Drizzle · Redis · BullMQ · Turborepo
Twendee ERP (host ERP) HR, payroll, attendance, accounting, CRM, projects NestJS 10 · React 18 · PostgreSQL · Docker
Sales Agent (specialised vertical) Lead enrichment (Apollo), Chrome extension, sales kanban Rust (Axum) backend · React frontend · Chrome MV3

Inside the Agents Hub:

TWDAgentsHub/
├── apps/
│   ├── api/              @twd/api          NestJS modular monolith
│   ├── admin-ui/         @twd/admin-ui     Tenant + agent + bot console
│   └── chat-widget/      @twd/chat-widget  Embeddable web widget
├── packages/
│   ├── shared-types/     @twd/shared-types Cross-app TS contracts
│   └── erp-adapters/     @twd/erp-adapters Pluggable ERP connectors
├── tooling/              tsconfig + tailwind preset
├── docs/                 architecture, codebase-summary, MCP wiring guide
└── docker-compose.yml    postgres:16 + redis:7

Engineering highlights

[!TIP] The non-obvious decisions — what a recruiter or new hire should know.

  • Dynamic agents over hard-coded ones. Agent prompts, tool whitelists, and LLM tier are stored in dynamic_agent_definitions keyed by tenantId. Adding a new vertical (e.g. Legal) is a DB row, not a deploy.
  • 3-layer prompt assembly. System contract → tenant policy → user input. Policy injection is the only sanctioned way to constrain agent behaviour per tenant. Prevents tenant-A from being prompt-injected into tenant-B's data.
  • Async webhook pattern for Telegram. 200 OK in <100ms via BullMQ deferral. Idempotency on update_id via Redis SETNX. No retry storms even when LLM stalls.
  • Per-tenant LLM tier routing. LlmProviderFactory resolves provider at runtime — Sonnet for Pro, Haiku for Free, BYOK for Enterprise. Same agent code; cost lever is config.
  • RLS first, app guards second. Tenant isolation is enforced in Postgres. App-level guards are belt-and-braces, not the security boundary.
  • Token metering in Redis, not Postgres. Per-tenant counters with TTL = billing window. Cheap reads, atomic increments.
  • Encrypted bot tokens. channel_bots.bot_token is AES-GCM encrypted with a per-tenant DEK. Compromise of one tenant's bot does not leak others.

Roadmap

  • Phase 1 — Foundation (auth, tenants, dynamic agents, REST chat)
  • Phase 2 — Channel bots (Telegram path-routed webhooks)
  • Phase 3 — Sales vertical (Apollo enrichment, kanban pipeline)
  • Phase 4 — RAG over tenant docs (per-tenant ChromaDB collections)
  • Phase 5 — Voice channel (Twilio + Whisper + ElevenLabs)
  • Phase 6 — MCP server exposure (each agent surfaced as an MCP tool to external IDEs)

Contact

Author Tran Phong
Email [email protected]
GitHub @phong28zk
LinkedIn fn28chen
Location Hanoi, Vietnam

[!NOTE] Source code is private. Happy to walk through architecture, agent runtime, and trade-offs in interviews. Reach out for a guided demo.

License

Documentation under CC BY 4.0. Architecture descriptions and diagrams may be cited with attribution.

from github.com/phong28zk/ai-agentic-erp-builder

Installing Ai Agentic Erp Builder

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/phong28zk/ai-agentic-erp-builder

FAQ

Is Ai Agentic Erp Builder MCP free?

Yes, Ai Agentic Erp Builder MCP is free — one-click install via Unyly at no cost.

Does Ai Agentic Erp Builder need an API key?

No, Ai Agentic Erp Builder runs without API keys or environment variables.

Is Ai Agentic Erp Builder hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Ai Agentic Erp Builder in Claude Desktop, Claude Code or Cursor?

Open Ai Agentic Erp Builder on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Ai Agentic Erp Builder with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All data MCPs