{"slug": "a-simple-way-to-add-ai-to-your-app-without-locking-yourself-to-one-provider", "title": "A Simple Way to Add AI to Your App Without Locking Yourself to One Provider", "summary": "A developer outlines a pattern for adding large language models to applications through a thin, provider-agnostic AI layer, using the open-source Vercel AI SDK in TypeScript to route requests between OpenAI, Anthropic, and local models. The approach centralizes model selection, retries, logging, and observability in one module so that switching or mixing providers does not require touching controllers, routes, or UI code. The writeup also points to LiteLLM for a unified self-hosted gateway and the Model Context Protocol for exposing tools and resources to AI clients.", "body_md": "Adding an LLM to an application is easy.\n\nThe annoying part usually comes six months later.\n\nMaybe you started with OpenAI, then another model becomes better for one particular task. Or you want to use a cheaper model for background jobs and a stronger model for user-facing requests.\n\nIf model-specific code is scattered throughout the application, changing providers becomes unnecessarily painful.\n\nA pattern I like is keeping the AI layer very small.\n\nFor a TypeScript project, an open-source option for this is the AI SDK.\n\nInstall the core package and whichever providers you need:\n\n```\nnpm install ai @ai-sdk/openai @ai-sdk/anthropic\n```\n\nInstead of calling provider SDKs directly from controllers, routes, or UI code, create one small AI module.\n\n``` js\n// lib/ai.ts\n\nimport { generateText } from \"ai\";\nimport { openai } from \"@ai-sdk/openai\";\nimport { anthropic } from \"@ai-sdk/anthropic\";\n\nconst models = {\n  openai: openai(process.env.OPENAI_MODEL!),\n  anthropic: anthropic(process.env.ANTHROPIC_MODEL!)\n};\n\nexport async function askAI(\n  prompt: string,\n  provider: keyof typeof models = \"openai\"\n) {\n  const { text } = await generateText({\n    model: models[provider],\n    prompt\n  });\n\n  return text;\n}\n```\n\nNow the rest of the application doesn't really care which company is serving the model.\n\n``` js\nconst summary = await askAI(\n  \"Summarize this customer support conversation\",\n  \"anthropic\"\n);\n```\n\nThe useful part isn't saving a few lines of code.\n\nIt's creating a boundary.\n\nOnce AI starts appearing in multiple parts of a product, it's very easy to end up with something like this:\n\n``` php\n/api/chat        -> Provider A\n/api/summarize   -> Provider A\n/jobs/classify   -> Provider A\n/api/search      -> Provider A\n/admin/generate  -> Provider A\n```\n\nThen configuration, retries, logging and prompts slowly get duplicated everywhere.\n\nI'd rather have:\n\n```\nApplication\n    |\n    v\nAI Layer\n    |\n    +---- Provider A\n    +---- Provider B\n    +---- Local/Open Model\n```\n\nThe application talks to your AI layer.\n\nThe AI layer decides where the request goes.\n\nOnce this abstraction exists, routing doesn't need to be static either.\n\nFor example:\n\n```\nexport async function generateForTask(\n  task: \"classification\" | \"reasoning\",\n  prompt: string\n) {\n  const provider =\n    task === \"classification\"\n      ? \"openai\"\n      : \"anthropic\";\n\n  return askAI(prompt, provider);\n}\n```\n\nIn a real application I would probably take this further and route based on things like:\n\nThis also gives you one place to add observability.\n\n``` js\nconst started = Date.now();\n\ntry {\n  const result = await askAI(prompt, provider);\n\n  console.log({\n    provider,\n    duration: Date.now() - started,\n    success: true\n  });\n\n  return result;\n} catch (error) {\n  console.error({\n    provider,\n    duration: Date.now() - started,\n    success: false\n  });\n\n  throw error;\n}\n```\n\nNothing complicated, but suddenly debugging AI requests becomes much easier.\n\nAnother thing I try to avoid is letting the UI know too much about the underlying provider.\n\nThe frontend should ideally call something like:\n\n```\nPOST /api/summarize\n```\n\nrather than:\n\n```\nPOST /api/openai/generate\n```\n\nYour product feature is **summarization**.\n\nOpenAI, Anthropic, Gemini or a local model is an implementation detail.\n\nThat distinction becomes useful surprisingly quickly.\n\nThere are a few interesting projects solving different parts of this problem.\n\n**Vercel AI SDK** provides a common TypeScript interface for working with multiple AI providers.\n\n**LiteLLM** takes a similar idea further on the infrastructure side, providing a unified interface and an optional self-hosted gateway for many different model providers.\n\nFor applications that need tools and external integrations, **Model Context Protocol (MCP)** is also worth looking at. Instead of writing a completely different integration system for every AI client, MCP provides a common protocol for exposing tools and resources.\n\nThey solve different problems, but they point in roughly the same direction:\n\nKeep your application architecture separate from whichever AI model happens to be popular today.\n\nI don't think most applications need a huge \"AI platform\" abstraction from day one.\n\nA small module is usually enough.\n\nThe important part is simply avoiding provider-specific calls everywhere in the codebase.\n\nStart with:\n\n``` php\nApp -> AI abstraction -> Provider\n```\n\nThen add routing, fallbacks, logging, caching and more advanced infrastructure only when the application actually needs them.\n\nAI models are changing too quickly to make them the foundation of your application architecture.\n\nYour product should depend on a capability.\n\nNot a model name.", "url": "https://wpnews.pro/news/a-simple-way-to-add-ai-to-your-app-without-locking-yourself-to-one-provider", "canonical_source": "https://dev.to/aarnavsaboo/a-simple-way-to-add-ai-to-your-app-without-locking-yourself-to-one-provider-5f8h", "published_at": "2026-10-02 04:43:21+00:00", "updated_at": "2026-10-02 05:14:43.847222+00:00", "lang": "en", "topics": ["ai-tools", "large-language-models", "developer-tools", "agent-protocols", "ai-agents"], "entities": ["Vercel AI SDK", "LiteLLM", "Model Context Protocol", "OpenAI", "Anthropic", "TypeScript", "Gemini"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/a-simple-way-to-add-ai-to-your-app-without-locking-yourself-to-one-provider", "markdown": "https://wpnews.pro/news/a-simple-way-to-add-ai-to-your-app-without-locking-yourself-to-one-provider.md", "text": "https://wpnews.pro/news/a-simple-way-to-add-ai-to-your-app-without-locking-yourself-to-one-provider.txt", "jsonld": "https://wpnews.pro/news/a-simple-way-to-add-ai-to-your-app-without-locking-yourself-to-one-provider.jsonld"}}