O Vercel AI SDK oferece uma única superfície elegante e agnóstica de provedor — generateText, streamText, tools e structured output — para construir aplicações agentic. O provider oficial @ai-sdk/azure, no entanto, cobre apenas o chat da Azure OpenAI, deixando de fora o restante do catálogo do Microsoft Foundry: Llama, DeepSeek, Mistral, Phi e agora Anthropic Claude.
TL;DR: O Vercel AI SDK oferece uma camada única e agnóstica para construir agentes, mas o provider oficial para Azure só cobre Azure OpenAI. Este artigo mostra como criar dois adapters — um compatível com OpenAI e outro com Anthropic — para acessar todo o catálogo do Microsoft Foundry (Llama, DeepSeek, Mistral, Claude etc.) sem modificar o código de aplicação. A conclusão prática: é possível integrar Foundry de forma limpa, mantendo a portabilidade do AI SDK e usando autenticação via Entra ID ou API key.
Qual a justificativa técnica?
Se você já entregou agentes com o Vercel AI SDK, conhece o apelo: uma superfície limpa com generateText, streamText e tools que permite trocar modelos e provedores sem tocar na lógica de orquestração. Essa portabilidade é o ponto central.
O problema é que, ao mover esses agentes para o Azure, o provider oficial @ai-sdk/azure fica restrito à chat API da Azure OpenAI. Ele constrói URLs como https://{resourceName}.openai.azure.com/openai/v1{path} e autentica especificamente para Azure OpenAI. Portanto, se você quiser usar modelos do catálogo Foundry como Llama, DeepSeek, Mistral, Phi, Anthropic Claude e outros, um provider nativo "drop‑in" não está disponível.
O Microsoft Foundry foi projetado para atuar como um backplane multi‑modelo único, com um endpoint e um conjunto de credenciais que podem atender modelos de vários provedores. Ou seja, a dificuldade não é "como alcançar os modelos do Azure?", mas "como conectar o Foundry de forma limpa ao AI SDK para que o código existente do agente permaneça exatamente o mesmo?
Como funciona a arquitetura de alto nível?
A extensão introduz dois adapters de provedor que se posicionam entre a superfície agnóstica do AI SDK e as duas rotas paralelas do Foundry, baseadas no seguinte:
- O Foundry expõe modelos de muitos provedores por meio de um endpoint + uma credencial e aceita Chat Completions no estilo OpenAI para implantações OpenAI e não‑OpenAI quando você acessa
/openai/v1/. - O Claude fica em uma rota paralela
/anthropic/v1/, falando a Anthropic Messages API.
| Adapter | Rota Foundry | Protocolo | Provider AI SDK |
|---|---|---|---|
| Adapter compatível com OpenAI | /openai/v1/* |
OpenAI Chat Completions / Responses | @ai-sdk/openai-compatible |
| Adapter Anthropic | /anthropic/v1/* |
Anthropic Messages API | @ai-sdk/anthropic (com baseURL e headers customizados) |
Ambos os adapters compartilham as mesmas opções de autenticação (Entra ID como padrão, API key como fallback) e o mesmo padrão de roteamento de modelo (nome da deployment como modelId). O código no nível da aplicação (agentes, planners, routers, pipelines RAG) permanece inalterado.
Modelos OpenAI e OSS no Foundry via /openai/v1
As famílias de modelos Azure OpenAI (GPT‑4.1, GPT‑5.x, série o, etc.), além de Llama, DeepSeek, Mistral, Phi e modelos parceiros, são acessíveis pelo caminho compatível com OpenAI do Foundry (/openai/v1).
// providers/foundry-openai.ts
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
import { DefaultAzureCredential } from '@azure/identity';
const credential = new DefaultAzureCredential();
// Scope for OpenAI-compatible surface on Foundry
const FOUNDRY_AI_SCOPE = 'https://cognitiveservices.azure.com/.default';
// Provider configuration — endpoint targeting and auth selection. Pass either `resource` (shortcut) or `baseURL` (full override). Auth defaults to Entra ID; set `apiKey`.
export interface FoundryOpenAIOptions {
resource?: string; // Foundry resource name. Used to build the default base URL.
baseURL?: string; // Full base URL override,
// "https://<resource>.services.ai.azure.com/openai/v1".
tenantId?: string; // Optional Entra tenant ID where the Foundry resource lives.
apiKey?: string;// Optional Foundry resource API key for key based authentication
}
export function createFoundry(options: FoundryOpenAIOptions = {}) {
const baseURL =
options.baseURL ??
(options.resource
? `https://${options.resource}.services.ai.azure.com/openai/v1`
: process.env.FOUNDRY_RESOURCE
? `https://${process.env.FOUNDRY_RESOURCE}.services.ai.azure.com/openai/v1`
: undefined);
if (!baseURL) {
throw new Error(
'createFoundry: provide `resource`, `baseURL`, or set FOUNDRY_RESOURCE env var.',
);
}
// Auth mode A (default) — Entra ID via DefaultAzureCredential.
const credential = new DefaultAzureCredential(
options.tenantId ? { tenantId: options.tenantId } : undefined,
);
return createOpenAICompatible({
name: 'microsoft-foundry',
baseURL,
apiKey: 'placeholder-not-used',
fetch: async (input, init) => {
const token = (await credential.getToken(FOUNDRY_AI_SCOPE))?.token;
if (!token) throw new Error('Failed to acquire Entra ID token for Foundry');
const headers = new Headers(init?.headers);
headers.set('Authorization', `Bearer ${token}`);
return fetch(input, { ...init, headers });
},
});
}
Exemplo de código para testar o providers/foundry-openai.ts em três modelos diferentes (Azure OpenAI, DeepSeek e Moonshot AI):
import { generateText, streamText } from 'ai';
import { createFoundry } from './providers/foundry-openai';
// Pass the Foundry resource name (or a full baseURL) here.
const foundry = createFoundry({
resource: {Your Foundry Resource name},
// baseURL: 'https://{Your Foundry Resource name}.services.ai.azure.com/openai/v1', // alternative
});
// One AI SDK surface, three different Foundry models, zero transport changes.
const gpt = foundry.chatModel('gpt-4.1-mini');
const ds = foundry.chatModel('DeepSeek-V3.1');
const kimi = foundry.chatModel('Kimi-K2.6');
//const llama = foundry.chatModel('Llama-3.3-70B-Instruct');
// Simple generation
const { text } = await generateText({
model: gpt,
prompt: 'Say hello in one short sentence.',
});
console.log('[gpt-4.1-mini]', text);
const { text: dsText } = await generateText({
model: ds,
prompt: 'What is 2 + 2?',
});
console.log('[DeepSeek-V3.1]', dsText);
// Streaming
process.stdout.write('[kimi] ');
const stream = streamText({ model: kimi, prompt: 'Draft a one-line customer reply.' });
for await (const chunk of stream.textStream) process.stdout.write(chunk);
process.stdout.write('\n');
Se você preferir usar API key (apenas em dev ou não‑produção), utilize o seguinte código:
// Auth mode B — API key (used when `apiKey` is set or AZURE_FOUNDRY_API_KEY is in the environment). Foundry accepts the resource key via the
// `api-key` header on the OpenAI-compatible route.
const apiKey = options.apiKey ?? process.env.AZURE_FOUNDRY_API_KEY;
if (apiKey) {
return createOpenAICompatible({
name: 'microsoft-foundry',
baseURL,
apiKey: 'placeholder-not-used',
fetch: async (input, init) => {
const headers = new Headers(init?.headers);
headers.delete('Authorization');
headers.set('api-key', apiKey);
return fetch(input, { ...init, headers });
},
});
}
Anthropic Claude no Foundry via /anthropic/v1
O Claude no Foundry não fica atrás de /openai/v1. Ele é exposto em https://{resource}.services.ai.azure.com/anthropic/v1/* e fala a Anthropic Messages API, não o formato Chat Completions do OpenAI. Portanto, @ai-sdk/openai-compatible não pode ser usado; em vez disso, utilize @ai-sdk/anthropic.
import { createAnthropic } from "@ai-sdk/anthropic";
import { DefaultAzureCredential } from "@azure/identity";
const SCOPE = "https://cognitiveservices.azure.com/.default";
export interface AnthropicFoundryOptions {
/** Foundry resource hostname or full URL, e.g. "https://<resource>.services.ai.azure.com" */
endpoint: string;
/** Optional Entra tenant ID where the Foundry resource lives */
tenantId?: string;
// OPTIONAL: Key-based authentication (uncomment to use API key instead of Entra ID). If `apiKey` is provided, it will be used directly and //DefaultAzureCredential will be skipped.
// apiKey?: string;
export function createAnthropicFoundry(options: AnthropicFoundryOptions) {
const url = new URL(options.endpoint);
const baseURL = `${url.protocol}//${url.host}/anthropic/v1`;
const credential = new DefaultAzureCredential(
options.tenantId ? { tenantId: options.tenantId } : undefined,
);
return createAnthropic({
baseURL,
// apiKey is required by the provider but unused; overriding the Authorization header per-request via custom fetch.
apiKey: "placeholder-not-used",
fetch: async (input, init) => {
// Entra ID (default) — acquire a bearer token via DefaultAzureCredential.
const token = (await credential.getToken(SCOPE))?.token;
if (!token) throw new Error("Failed to acquire Entra ID token");
// OPTION B: Key-based authentication (uncomment to use API key). Foundry accepts the resource key via the `api-key` header.
// Comment out the Entra block above when enabling this.
// const apiKey = options.apiKey ?? process.env.AZURE_FOUNDRY_API_KEY;
// if (!apiKey) throw new Error("Missing Foundry API key");
const headers = new Headers(init?.headers);
// Strip Anthropic's default API key header and replace with bearer token
headers.delete("x-api-key");
headers.set("Authorization", `Bearer ${token}`);
// For key-based auth, replace the line above with:
// headers.set("api-key", apiKey);
return fetch(input, { ...init, headers });
},
});
}
}
Exemplo de teste para o modelo Claude:
// Test using AI-sdk/anthropic against a Microsoft Foundry endpoint with Entra ID.
import { generateText } from "ai";
import { createAnthropicFoundry } from "./providers/anthropic-foundry";
const anthropic = createAnthropicFoundry({
endpoint: "https://<your-foundry-resource>.services.ai.azure.com",
tenantId: process.env.AZURE_TENANT_ID, // optional (only needed if multi-tenant)
// OPTIONAL: Key-based authentication. Uncomment to use an API key instead of Entra ID (DefaultAzureCredential). Requires enabling the
// matching `apiKey` branch in providers/anthropic-foundry.ts.
// apiKey: process.env.AZURE_FOUNDRY_API_KEY,
});
const { text } = await generateText({
model: anthropic("claude-opus-4-7"), // replace with your Foundry model deployment name
prompt: "Hello!",
});
console.log(text);
Essa abordagem permite conexões perfeitas entre sistemas, garantindo flexibilidade, escalabilidade e segurança.
Resumo
| Categoria de Modelo no MS Foundry | Tipo de Endpoint Utilizado | Padrão de Integração com Vercel AI SDK | Opções de Autenticação |
|---|---|---|---|
| Modelos compatíveis com OpenAI (OpenAI, DeepSeek, Moonshot AI, Mistral AI, Meta etc.) | Endpoint /openai/v1 compatível com OpenAI |
Uso nativo do SDK (funciona com override de baseURL) |
• API Key • Microsoft Entra ID (token) |
| Anthropic Claude | Endpoint Anthropic Messages API | Usa padrão de provider (não é compatível com OpenAI) | • API Key • Microsoft Entra ID (token) |
Próximos passos
Pronto para começar a construir? Aqui estão seus caminhos:
- Microsoft Foundry Models - Visão geral dos modelos Foundry
- Microsoft Foundry Model endpoints - Endpoints para modelos Foundry e como acessá-los
- Vercel AI SDK docs - Conceitos centrais e padrões avançados
- Anthropic on Foundry guide - Implantar e usar modelos Claude no MS Foundry
Perguntas Frequentes
-
Por que o provider oficial do AI SDK para Azure não funciona com Foundry?
O provider oficial@ai-sdk/azurefoi construído exclusivamente para o endpoint de chat do Azure OpenAI, usando URLs comohttps://{resource}.openai.azure.com/openai/v1/.... O Microsoft Foundry expõe modelos de terceiros (Llama, DeepSeek, Claude etc.) em endpoints diferentes, como/openai/v1/e/anthropic/v1/, que exigem adaptadores separados. -
Quais modelos podem ser acessados via o adapter OpenAI?
Modelos da família Azure OpenAI (GPT-4.1, GPT-5.x, o‑series), Llama, DeepSeek, Mistral, Phi e outros modelos de parceiros que seguem o formato Chat Completions do OpenAI — todos disponíveis no caminho/openai/v1/do Foundry. -
Como autenticar contra o Foundry usando o adapter?
O suporte padrão é via Entra ID (token Bearer obtido comDefaultAzureCredential), mas também é possível usar API key (recomendado apenas para ambientes de desenvolvimento ou não‑produção). Ambos os adapters aceitam as duas opções. -
O código da aplicação precisa ser alterado para usar os adapters?
Não. Os adaptadores implementam a interface padrão do Vercel AI SDK (createOpenAICompatibleecreateAnthropic). O código de geração de texto, streaming e ferramentas permanece exatamente o mesmo; apenas a configuração do provider é substituída. -
O Claude no Foundry segue o mesmo padrão dos outros modelos?
Não. O Claude é exposto em um endpoint separado (/anthropic/v1/) que usa a Anthropic Messages API, não o formato OpenAI. Por isso, o adapter para Claude utiliza o pacote@ai-sdk/anthropiccom configuração customizada debaseURLe headers.
Artigo originalmente publicado em Azure Updates - Latest from Azure Charts.