FRD: AI Provider Real Implementation
| Field | Value |
|---|---|
| ID | FRD-045 |
| Owner | David Holmes |
| Status | Draft |
| Last Updated | 2026-06-02 |
| Open Source Libraries | ai (Vercel AI SDK), @ai-sdk/anthropic, @ai-sdk/openai |
| Documentation | Vercel AI SDK Docs · Anthropic Provider · OpenAI Provider |
| Related | ADR-027 (Default Tech Stack), ADR-014 (Open Source First) |
| Target Release | v2.1.0 |
| Type | Library |
| Complexity | S |
Document Summary
This FRD ships @dmwd-io/ai — an optional design-system package that re-exports the Vercel AI SDK as the platform standard for AI features. There is no custom adapter layer. Developers import from @dmwd-io/ai instead of directly from ai; the design system controls the version, the provider choices, and the conventions. If we ever swap the underlying SDK, one package changes and all apps update.
Introduction
Overview
AI features (text generation, chat threads, structured output, streaming) appear in more applications each release. Without a designated standard, every app researches the same options — Vercel AI SDK, LangChain, direct Anthropic/OpenAI SDK calls — and lands on different answers. That drift makes it harder to share patterns, upgrade safely, or add platform-level conventions like default model names and env var standards.
Per ADR-014 (Open Source First), the right answer is not to build a custom AiProvider interface and adapters. The Vercel AI SDK already handles multi-provider support, streaming, structured output with Zod validation, and retry. We designate it as the standard and expose it through our namespace.
Goals
- Designate the Vercel AI SDK as the platform standard for AI features.
- Ship
@dmwd-io/aias an optional package that re-exports the SDK under the design system’s namespace. - Document default model names, env var conventions, and recommended import patterns.
- Give teams one place to import AI primitives — no per-app research needed.
Non-Goals
- Building a custom
AiProviderinterface or adapter layer. - Re-implementing streaming, structured output, or retry — the SDK handles these.
- Locking teams to a specific provider — the SDK supports Anthropic, OpenAI, Google, Mistral, and many others.
- Server infrastructure for AI (proxies, cost metering) — application concerns.
Why the Vercel AI SDK
The SDK is maintained by Vercel, has strong community adoption, and covers the full surface area needed:
| Capability | SDK primitive |
|---|---|
| Text generation | generateText() |
| Streaming responses | streamText() — yields tokens via AsyncIterableIterator<string> |
| Structured output with Zod | generateObject({ schema }) — validation built in |
| Multi-provider | @ai-sdk/anthropic, @ai-sdk/openai, @ai-sdk/google, 20+ others |
| Retry on rate limits | maxRetries option on every call |
| Tool use / function calling | tools option on generateText/streamText |
| React hooks for chat UI | useChat, useCompletion from ai/react |
Full documentation: sdk.vercel.ai/docs
Package Structure
The @dmwd-io/ai package has three entry points that mirror the SDK’s own structure:
// Core SDK — generateText, streamText, generateObject, useChat, etc.import { generateText, streamText, generateObject } from '@dmwd-io/ai';
// Anthropic provider (default platform choice per ADR-027)import { anthropic } from '@dmwd-io/ai/anthropic';
// OpenAI provider (alternative)import { openai } from '@dmwd-io/ai/openai';Each entry point is a direct re-export of the corresponding SDK package with no wrapper:
export * from 'ai';
// packages/ai/src/anthropic.tsexport * from '@ai-sdk/anthropic';
// packages/ai/src/openai.tsexport * from '@ai-sdk/openai';Conventions
Default models
| Provider | Default model | Env var |
|---|---|---|
| Anthropic | claude-sonnet-4-6 | ANTHROPIC_API_KEY |
| OpenAI | gpt-4o | OPENAI_API_KEY |
Recommended usage pattern
import { generateText } from '@dmwd-io/ai';import { anthropic } from '@dmwd-io/ai/anthropic';
const { text } = await generateText({ model: anthropic('claude-sonnet-4-6'), system: 'You are a helpful assistant.', prompt: 'Summarize this document.',});Streaming
import { streamText } from '@dmwd-io/ai';import { anthropic } from '@dmwd-io/ai/anthropic';
const { textStream } = streamText({ model: anthropic('claude-sonnet-4-6'), prompt: 'Write a short story.',});
for await (const chunk of textStream) { process.stdout.write(chunk);}Structured output
import { generateObject } from '@dmwd-io/ai';import { anthropic } from '@dmwd-io/ai/anthropic';import { z } from 'zod';
const { object } = await generateObject({ model: anthropic('claude-sonnet-4-6'), schema: z.object({ title: z.string(), tags: z.array(z.string()) }), prompt: 'Classify this article.',});React chat UI
import { useChat } from '@dmwd-io/ai/react';
// Same API as ai/react — see sdk.vercel.ai/docs/ai-sdk-ui/chatbotDependencies
| Dependency | Type | Notes |
|---|---|---|
ai | peerDependency | Vercel AI SDK core |
@ai-sdk/anthropic | peerDependency | Anthropic provider — install when using Anthropic |
@ai-sdk/openai | peerDependency | OpenAI provider — install when using OpenAI |
| ADR-027 | Governance | Designates Anthropic as primary AI provider |
| ADR-014 | Governance | Open Source First — no custom adapter layer |
Risks and Tradeoffs
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Vercel AI SDK has a breaking change. | Low | Medium | Pin a major version in @dmwd-io/ai. All apps update together on a deliberate upgrade. |
Teams bypass @dmwd-io/ai and import ai directly. | Medium | Low | Linting rule (no-restricted-imports) can enforce the namespace. Drift is visible in package.json. |
| SDK doesn’t support a needed provider. | Low | Low | The SDK supports 20+ providers. If a new one is needed, add @ai-sdk/<provider> to the package. |
Acceptance Criteria
-
@dmwd-io/aipackage exists withindex.ts,anthropic.ts, andopenai.tsentry points. -
import { generateText } from '@dmwd-io/ai'works in a consuming app. -
import { anthropic } from '@dmwd-io/ai/anthropic'works. -
import { openai } from '@dmwd-io/ai/openai'works. - Default model names and env var names are documented in the package README.
-
pnpm typecheckpasses.
LLM Handoff Instructions
- Create
packages/ai/withpackage.json,tsconfig.json,src/index.ts,src/anthropic.ts,src/openai.ts. src/index.ts:export * from 'ai'src/anthropic.ts:export * from '@ai-sdk/anthropic'src/openai.ts:export * from '@ai-sdk/openai'- Add
ai,@ai-sdk/anthropic,@ai-sdk/openaias peer dependencies inpackage.json. - Add the package to the monorepo workspace.
- Verify
pnpm typecheckpasses.
Do not build a custom AiProvider interface, custom adapters, or a factory function. The SDK is the interface.
Decision Log
| Date | Decision | Rationale |
|---|---|---|
| 2026-06-02 | Reframed from custom adapter layer to thin re-export package. | ADR-014 (Open Source First): the Vercel AI SDK already provides multi-provider support, streaming, structured output, and retry. Building a custom interface on top would duplicate its capabilities while constraining API surface. |
| 2026-06-02 | Vercel AI SDK as the designated standard. | Largest community, broadest provider coverage, active maintenance, first-class Zod integration, React hooks included. |
| 2026-06-02 | Anthropic as default provider per ADR-027. | Platform preference; OpenAI available as drop-in alternative via same SDK. |
Document History
| Version | Date | Author | Changes |
|---|---|---|---|
| 0.1 | 2026-05-26 | David Holmes | Initial draft. |
| 0.2 | 2026-05-26 | David Holmes | Revised to use Vercel AI SDK as thin-wrapper foundation. |
| 1.0 | 2026-06-02 | David Holmes | Reframed per ADR-014: drop custom adapter layer entirely, ship as re-export package. |