The Adapter Pattern is a structural design pattern that makes an existing interface usable through the interface an application expects. The application calls a stable contract, and an adapter translates that call into the operations required by a particular implementation. In cloud systems, adapters commonly sit between business logic and external APIs, storage systems, payment providers, or foundation model endpoints. The objective is to contain integration differences rather than spread provider-specific conditions throughout application code.
For foundation model integration, define an application-facing contract containing messages, generation settings, tool definitions, and an explicit response format. Each provider adapter maps supported fields into the provider's request schema and converts its response into a common result. That result might contain generated content, normalized completion status, usage information, and provider metadata. Streaming requires its own contract for incremental content, tool-call events, completion, and errors; a synchronous response wrapper does not automatically provide streaming compatibility.
A practical architecture exposes a stable endpoint through Amazon API Gateway and invokes adapter logic hosted in AWS Lambda. A routing component reads AWS AppConfig configuration that maps a logical model name, such as support-assistant, to an approved provider, model identifier, and adapter. The application continues calling the same endpoint while operators change the configuration. Configuration can also express approved fallback targets or rollout settings. Adapters perform interface translation; routing or strategy logic decides which adapter to invoke. These responsibilities are related but distinct.
Switching without code modifications is possible when the target provider and capabilities are already supported by deployed adapters. Adding an incompatible provider generally requires implementing and deploying another adapter, but the calling application can remain unchanged. Configuration updates also need validation, controlled rollout, and monitoring. Applications must retrieve refreshed configuration rather than load it permanently at startup, and operators should account for caching and deployment propagation time.
A common misconception is that a uniform API makes models interchangeable. Models differ in context limits, tokenization, tool support, structured output behavior, safety controls, and response quality. Validate required capabilities before routing and reject unsupported options rather than silently discarding them. Amazon Bedrock Converse provides a common interface across supported models, reducing translation work, but model-specific capabilities and parameters still require explicit handling.
Adapters introduce maintenance work and can hide useful provider features if the shared contract is too restrictive. Use a small stable core with explicit capability checks and carefully controlled extensions. Normalize errors while retaining diagnostic details, apply bounded retries only to suitable failures, and recognize that retries can incur additional inference charges. Automatic fallback must respect data residency, authorization, and approved-provider policies rather than send sensitive prompts to any available endpoint. Record the selected model, configuration version, latency, usage, and outcome without unnecessarily logging sensitive prompts. Contract tests and model evaluations should verify both interface compatibility and task quality before a routing change reaches production.