Build a Type-Safe Multi-Model AI Router
π Technical Briefing: This tutorial is part of our deep-dive series on Agentic Workflows at Gate of AI. For the full technical breakdown, interactive code sandbox, and the native Arabic translation, visit the original ar
π Technical Briefing: This tutorial is part of our deep-dive series on Agentic Workflows at Gate of AI. For the full technical breakdown, interactive code sandbox, and the native Arabic translation, visit the original article here.
Tutorial Β· Verification-first architecture guide
Build a Type-Safe Multi-Model AI Chat Router
This guide explains how to plan and verify a Next.js application that routes chat requests to more than one model provider. It focuses on the boundaries that must be established before code is treated as production-ready: a shared request contract, server-side provider integration, explicit model selection, and a version-security review. The available verified sources do not establish current OpenAI or Anthropic JavaScript SDK syntax, supported model identifiers, or response schemas. Accordingly, this article does not present unverified provider calls as working code.
What the Available Evidence Establishes
Next.js is a React framework for building web applications. The supplied sources also describe KISS Sorcar, a separate assistant framework that catalogs models across multiple provider categories, including OpenAI and Anthropic. Its description says tasks can mix models by referencing a different model ID and that the framework swaps the backend per call. These facts demonstrate that multi-provider model selection is a real software pattern, but they do not document a Next.js route handler or prove that a particular OpenAI or Anthropic SDK integration works.
That distinction matters. A tutorial can safely explain design goals and verification steps without pretending that every library call has been checked. SDKs evolve, model names change, and provider request and response formats are not interchangeable by default. Before copying code into an application, consult the current official documentation for each provider and test against the exact package versions and models you intend to deploy.
This guide therefore treats the implementation as a sequence of engineering decisions. It does not claim that a particular model is available to every account, that a specific token parameter is accepted by both providers, or that one normalized response shape captures every provider capability. Those are integration details to verify independently.
Step 1: Define the Routerβs Scope
Write down what βmulti-model routerβ means for your application before choosing a package or creating a user interface. At minimum, decide whether a user selects a provider, a model, or a preconfigured combination of both. A provider selector alone is not a model registry: each provider can expose multiple models, and availability may depend on account access or configuration.
Also decide whether the first version handles text-only chat. The supplied context does not verify support for images, tools, structured output, streaming, or multimodal requests through the proposed Next.js implementation. Do not imply those capabilities merely because a provider or another framework may support them. Keep the initial contract narrow and add a capability only after checking the provider documentation and testing the relevant request and response paths.
Write down the user-visible result you need. A small interface might show the selected provider and model alongside the answer. That is a product decision, not proof that the provider returned the requested model. Where the provider returns an identifier, verify and report the actual response value according to its current API documentation.
Step 2: Create a Shared Request Contract
Use an application-owned request format rather than allowing provider-specific data structures to spread through the UI. A contract should specify the permitted provider identifiers, the accepted message roles, message content limits, and how the selected model is represented. Validate incoming HTTP data at runtime: TypeScript types describe values during development, but they do not by themselves validate arbitrary JSON received by a server.
Make role policy explicit. If the client is expected to send only user messages and a system instruction, encode that policy in the runtime validator and test it. If earlier assistant turns must be sent to preserve conversational context, specify that intentionally and validate their order. Do not claim that assistant messages are rejected while writing a schema that accepts them. The draft implementation had precisely this contradiction: its role enum included assistant even though its explanatory text said assistant messages could not be sent.
Likewise, validate the relationship between provider and model on the server. A browser dropdown is a convenience for users, not a security boundary. A request can be altered outside the interface. Keep an approved list or registry in server-controlled configuration and reject combinations that the application has not explicitly enabled. The supplied sources do not establish a current list of OpenAI or Anthropic model IDs, so populate this registry only after checking official provider information.
Choose request-size limits based on your product requirements and test them. A character limit can bound the size of a text field, but it is not a token count and should not be presented as one. Provider-specific token accounting, output limits, and billing behavior must be confirmed with the relevant provider documentation.
Step 3: Keep Provider Calls Behind a Server Boundary
For a web application, design the browser-to-server boundary before connecting a model. The browser should submit an application request to your own server endpoint; the server is where provider credentials and provider-specific integration belong. Do not place secrets in browser-visible configuration or return them in responses. Verify the actual framework conventions and deployment settings for the Next.js version you use.
Use a separate adapter for each provider. Each adapter should translate the shared application contract into the providerβs documented request format and translate the documented response into your applicationβs result format. Treat that normalized response as an application abstraction, not as evidence that provider capabilities are identical. If one provider returns content in multiple blocks or exposes additional metadata, handle that according to its official documentation instead of assuming a text field exists in a particular location.
Before publishing an adapter, verify its package name, installed version, initialization method, method names, required fields, response parsing, and error behavior against official documentation. The verified context supplied for this review does not confirm the draftβs specific JavaScript SDK calls or model identifiers. Therefore, copying those exact calls from the original draft without independent checking would be unsafe.
Return errors that help the application behave correctly without exposing credentials or raw sensitive request data. Distinguish malformed input from a missing server configuration and an upstream provider failure. Avoid logging full prompts by default unless your organization has reviewed the data, retention, access, and consent implications. These are implementation recommendations; they are not claims that the original code already enforces them.
Step 4: Make Model Selection Server-Authoritative
A model selector should be backed by server-side configuration. For each enabled option, record the provider and the exact model identifier verified against current official documentation. The server should reject unknown providers, unknown models, and unsupported pairings before making an upstream request. This keeps a modified browser request from selecting arbitrary values the application did not intend to support.
The supplied description of KISS Sorcar offers a useful example of the general concept: it reports a catalog containing OpenAI and Anthropic model categories and describes switching the backend when a task references a different model ID. That is evidence about KISS Sorcar, not about this tutorialβs proposed Next.js router. Do not imply that KISS Sorcar is a dependency, that its model catalog applies to your application, or that its behavior validates a particular SDK implementation.
When you add another model, check the providerβs current documentation and account access first. Then update the server-owned registry, the user-facing label, and tests for valid and invalid pairings. Avoid hard-coding a model name in multiple places: duplications make it easier for the interface and server policy to drift apart.
Step 5: Verify Next.js Security and Deployment Versions
Security review is part of building a router, not a post-launch cleanup task. The supplied NVD context lists several Next.js issues and specific affected version ranges. CVE-2026-44572 affects versions from 12.2.0 up to, but not including, 15.5.16, and versions from 16.0.0 up to, but not including, 16.2.5. The supplied description concerns a middleware redirect behavior involving an x-nextjs-data header and possible cached redirect responses in deployments behind a CDN or reverse proxy.
The context also lists CVE-2026-44581 and CVE-2026-44580, with the stated fixed thresholds of 15.5.16 and 16.2.5. The summaries describe issues involving CSP nonces with shared caches and beforeInteractive scripts with untrusted content, respectively. Check the NVD records and the relevant vendor advisories for the exact impact, affected configurations, and remediation before making a deployment decision.
Do not assume that selecting a version described as βNext.js 15 or newerβ is sufficient. That range can include affected releases. Check the exact version resolved by your lockfile and deployed artifact, then use a release that includes the applicable fixes. Review the deployment architecture as well: shared caches, middleware, script usage, and reverse proxies can affect exposure. The existence of a vulnerability record does not establish that every application is vulnerable in the same way.
Step 6: Test Contracts Before Testing Paid Model Calls
Start with tests that do not contact a model provider. Test that an allowed request passes, an unknown provider fails, an unknown model fails, malformed JSON is handled, over-limit input is rejected, and role ordering follows the policy you documented. Add a test for each provider/model pairing in the server registry. These tests verify your applicationβs own contract; they do not prove that an upstream SDK call is valid.
Next, run a controlled integration test using credentials and a model that have been confirmed in current official provider documentation and are available to the account. Verify the actual HTTP status, response shape, and error path. Do not print credentials or full prompts into test logs. Record which package versions and model identifiers the test used so the result can be reproduced after a dependency or provider change.
Test failures deliberately: missing credentials, invalid provider configuration, upstream errors, timeouts, and invalid or incomplete response data. Handle those cases according to the current SDK and provider behavior. The original draft proposed specific HTTP status mappings and SDK response fields, but the supplied context does not establish that those details are correct for the proposed integrations.
Finally, run the applicationβs normal build and deployment checks for the exact Next.js version selected. Test the deployed route, not just the development server. Verify that secrets are not present in browser assets or public responses and that production configuration matches the server-side design.
Step 7: Fix the Draftβs Implementation Defects Before Reusing It
Several details in the original tutorial require correction independent of the provider documentation gap. Its schema accepts assistant as a message role, while the prose claims assistant messages cannot be sent by the client. Its server accepts any bounded model string rather than checking an approved provider/model pair. Its explanation calls for authentication and rate limits before real users access the route, but the sample route does not implement either control. Those gaps mean the sample should not be described as production-ready.
The shown shell examples also need to be checked. The Git ignore command uses unusual newline escapes, and the multiline curl examples omit shell line-continuation characters as rendered. Do not assume a code block works because it looks plausible. Copy it into a clean environment, run it, and include the exact command that succeeds. Likewise, verify the test and lint scripts against the selected Next.js and tooling versions rather than assuming a script from an older template remains valid.
Do not present rate limits, authentication, tenant budgets, observability, or moderation as features of the sample unless the code actually implements and tests them. They may be appropriate future work, but a list of possible improvements is not evidence that the current application provides those protections.
What to Confirm Before Adding Features
Once the basic path is validated, consider additional capabilities one at a time. Streaming requires provider-specific stream handling and a documented event contract. Tool calls require explicit authorization and validation. Structured output requires checking the providerβs supported format and validating the returned data. Usage reporting requires understanding the providerβs actual usage fields. None of these details is established by the sources supplied for this review.
Keep a short integration record for each provider: documentation checked, SDK package and version, verified model identifiers, request and response examples, known error handling, and test date. Recheck it when dependencies or provider documentation change. This is particularly important for a router because a change in one adapter can affect multiple user-facing model choices.
A sound multi-model router is not defined by the number of provider names in a dropdown. It is defined by a clear application contract, verified provider adapters, server-controlled model selection, tested failure handling, and a maintained dependency and security review. The available evidence supports the general idea of routing among models, but it does not certify the draftβs specific SDK code. Mark that distinction clearly until the integration is checked against current official sources.
Sources and Verification Notes
- Getting Started with Next.js: A Beginnerβs Guide describes Next.js as a React framework for web applications.
- KISS Sorcar describes its multi-provider model catalog and per-call model switching. Those are KISS Sorcar capabilities, not proof of this tutorialβs implementation.
- NVD: CVE-2026-44572 lists affected Next.js ranges and describes the redirect-cache issue.
- NVD Next.js search results include the supplied summaries for CVE-2026-44580 and CVE-2026-44581.
Editorial attribution: Gate of AI Editorial & Engineering Teams, GateOfAI, LLC.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.