Agent Studio
Adr

ADR-004: Monorepo Structure

Combined Python backend and TypeScript frontend in single repository

ADR-004: Monorepo Structure

Status

Accepted

Context

Agent Studio consists of:

  • Backend: Python FastAPI API + LiveKit worker
  • Dashboard: Next.js web application
  • Docs: Fumadocs documentation site

We need to decide how to organize these components.

Options Considered

  1. Separate repositories - Independent deployments, complex coordination
  2. Monorepo with shared types package - Type sharing via npm package
  3. Monorepo with OpenAPI generation - Generate TS types from Python
  4. Polyrepo with git submodules - Worst of both worlds

Decision

We will use a monorepo with separate package managers:

agent-studio/
├── src/agent_studio/           # Python backend (uv)
├── apps/
│   ├── dashboard/              # Next.js dashboard (pnpm)
│   └── docs/                   # Fumadocs site (pnpm)
├── pyproject.toml              # Python dependencies
├── uv.lock                     # Python lockfile
├── package.json                # Root workspace config
├── pnpm-workspace.yaml         # pnpm workspace
└── pnpm-lock.yaml              # JS/TS lockfile

Type Sharing Strategy

Instead of a shared-types package, we use OpenAPI → TypeScript generation:

  1. FastAPI generates OpenAPI spec automatically
  2. Build step generates TypeScript types from spec
  3. Dashboard imports generated types
# Generate types during build
pnpm --filter @agent-studio/dashboard run generate-types

Why Not shared-types Package?

  • Adds complexity (publish, version, sync)
  • Types are already defined in Python (Pydantic)
  • OpenAPI is the source of truth for API contracts
  • Generated types are always in sync

Workspace Configuration

# pnpm-workspace.yaml
packages:
  - 'apps/*'
// package.json (root)
{
  "name": "agent-studio",
  "private": true,
  "scripts": {
    "dev:dashboard": "pnpm --filter @agent-studio/dashboard dev",
    "dev:docs": "pnpm --filter @agent-studio/docs dev",
    "build": "pnpm -r build"
  }
}

Consequences

Positive

  • Single repository for all code
  • Atomic commits across frontend/backend
  • Shared CI/CD configuration
  • Easy local development
  • Types always in sync via OpenAPI

Negative

  • Two package managers (uv + pnpm)
  • Larger repository size
  • CI needs to handle both ecosystems

Neutral

  • Clear separation of Python and TypeScript code
  • Independent deployment possible
  • Shared tooling where applicable (git hooks, CI)

On this page