AI Toolkit

Architecture Decision Records

Key technical decisions and their rationale

ADR Index

These decisions were made during Phase 1 development and document the reasoning behind key architectural choices.

ADR-001: Vercel AI SDK Over Raw Providers

Decision: Use Vercel AI SDK as the AI abstraction layer instead of calling provider APIs directly.

Rationale: AI SDK provides a unified interface across providers (OpenAI, Anthropic, Groq, etc.), handles streaming, structured output, and tool calling. This eliminates provider-specific code in the adapter layer.

ADR-002: Drizzle Over Prisma for pgvector

Decision: Use Drizzle ORM instead of Prisma for database operations.

Rationale: Drizzle has first-class pgvector support, generates no client binary, and allows raw SQL when needed. Prisma's pgvector support is experimental and the generated client adds ~10MB.

ADR-003: Regex PII Detection Over ML Models

Decision: Use regex-based PII detection instead of ML models (like Presidio).

Rationale: Regex detection is zero-dependency, Edge-compatible, and fast. ML models require large binaries and Python interop. For a TypeScript toolkit, regex is the pragmatic choice. Trade-off: higher false positive rate, especially for names (Title Case patterns).

ADR-004: Langfuse Over LangSmith for Monitoring

Decision: Use Langfuse for AI observability instead of LangSmith.

Rationale: Langfuse is open-source, self-hostable, and has a clean JS SDK. LangSmith is proprietary and tightly coupled to LangChain. Langfuse supports any LLM provider.

ADR-005: LangChain for Composition, Not Orchestration

Decision: Use LangChain.js for prompt templates and output parsing, but NOT for agent orchestration (use LangGraph instead).

Rationale: LangChain's agent framework is complex and opinionated. LangGraph provides a cleaner graph-based model for multi-agent orchestration. LangChain excels at composition primitives.

ADR-006: LiteParse for PDF, Custom Pipeline Over LlamaIndex

Decision: Use @llamaindex/liteparse for PDF parsing with a custom ingestion pipeline instead of LlamaIndex's full framework.

Rationale: LlamaIndex's full framework is heavy and opinionated. LiteParse provides just the PDF parsing we need, and our custom pipeline (parse → chunk → embed → store) is simpler and more flexible.

ADR-007: Inngest for Durability Over Custom Queue

Decision: Use Inngest for durable workflow execution instead of building a custom job queue.

Rationale: Inngest provides automatic retries, step functions, cron scheduling, and human-in-the-loop — all battle-tested. Building equivalent durability guarantees from scratch would take months.

ADR-008: LangGraph for Graph Orchestration

Decision: Use LangGraph.js for multi-agent orchestration.

Rationale: LangGraph's state graph model naturally maps to multi-agent workflows with conditional routing, cycles, and human-in-the-loop checkpoints.

On this page

On this page