Wer mit den Azure OpenAI SDKs arbeitet, hat es in den letzten Monaten sicher gemerkt: Es bewegt sich gerade viel. Azure AI Studio wurde zu Azure AI Foundry, die SDKs werden konsolidiert, APIs umbenannt — und einiges davon hat harte Deadlines. Wer seine NuGet-Pakete nicht rechtzeitig aktualisiert, hat ab Mai 2026 ein echtes Problem.
Ich bin bei Thinktecture immer wieder auf Kundenprojekte gestoßen, die noch mit der 1.0-Beta von Azure.AI.OpenAI arbeiten. Der Code funktioniert — noch. Aber die Uhr tickt, und die Migration ist weniger trivial, als man denken könnte.
In diesem Artikel zeige ich, was sich konkret ändert, wie der alte und der neue Code aussieht, welche NuGet-Pakete ersetzt werden müssen, und wie man Agents von der Assistants API zur Responses API migriert.
Was sich geändert hat — und warum
Microsoft hat die gesamte AI-Plattform umstrukturiert. Die kurze Geschichte:
- Azure AI Studio → Azure AI Foundry → Microsoft Foundry (aktuell)
- Azure Cognitive Services → Azure AI Services → Foundry Tools (aktuell)
Die Namensänderungen betreffen nicht nur das Portal, sondern ziehen sich durch die gesamte SDK-Landschaft. Das Ziel: Weg von fragmentierten Azure-spezifischen SDKs, hin zu einem konsolidierten Paketmodell, das auf der standardisierten OpenAI-API aufbaut.
Für uns als .NET-Entwickler bedeutet das konkret:
- Der
OpenAIClientaus der 1.0-Beta weicht einemAzureOpenAIClientmit szenario-spezifischen Sub-Clients - API Keys als primäre Authentifizierung weichen
DefaultAzureCredential(Entra ID / Managed Identity) - Die Assistants API wird durch die Responses API ersetzt (Sunset: August 2026)
- Das Paket
Azure.AI.Inferencewird eingestellt (Mai 2026) Azure.AI.Projects1.x zielt auf das Classic-Portal, 2.x auf das neue Foundry-Portal
Das sind keine kosmetischen Änderungen. Das sind Breaking Changes mit festen Deadlines.
Der alte Code vs. der neue Code
Schauen wir uns die wichtigsten Änderungen im Code an. Ich zeige jeweils den alten 1.0-Beta-Code und die neue 2.x-Version.
Client-Konfiguration
Vorher — Azure.AI.OpenAI 1.0 Beta:
// Ein einzelner Client für alles, API Key als Credentials
OpenAIClient client = new(
new Uri("https://my-resource.openai.azure.com/"),
new AzureKeyCredential(
Environment.GetEnvironmentVariable("AZURE_OPENAI_API_KEY")));
Nachher — Azure.AI.OpenAI 2.x:
// Top-Level Azure Client, DefaultAzureCredential statt API Key
AzureOpenAIClient azureClient = new(
new Uri("https://my-resource.openai.azure.com/"),
new DefaultAzureCredential());
// Szenario-spezifische Clients werden vom Top-Level Client geholt
ChatClient chatClient = azureClient.GetChatClient("gpt-4o");
EmbeddingClient embeddingClient = azureClient.GetEmbeddingClient("text-embedding-3-small");
Die größte konzeptuelle Änderung: In 2.x gibt es einen Top-Level AzureOpenAIClient, von dem man sich szenario-spezifische Clients holt — ChatClient, EmbeddingClient, ImageClient, etc. Man arbeitet nicht mehr mit einem monolithischen Client, der alles kann.
Und ja: DefaultAzureCredential statt API Key ist die neue Standard-Empfehlung. Das bedeutet lokale Entwicklung mit Azure CLI Login, Managed Identity in Produktion. Wer noch API Keys in Konfigurationsdateien hat, sollte das sowieso schon längst geändert haben.
Chat Completions
Vorher:
var options = new ChatCompletionsOptions()
{
DeploymentName = "gpt-4o",
Messages =
{
new ChatRequestSystemMessage("Du bist ein hilfreicher Assistent."),
new ChatRequestUserMessage("Was ist Azure AI Foundry?"),
}
};
Response<ChatCompletions> response =
await client.GetChatCompletionsAsync(options);
string reply = response.Value.Choices[0].Message.Content;
Nachher:
ChatCompletion completion = await chatClient.CompleteChatAsync(
[
new SystemChatMessage("Du bist ein hilfreicher Assistent."),
new UserChatMessage("Was ist Azure AI Foundry?"),
]);
string reply = completion.Content[0].Text;
Deutlich schlanker. Kein Options-Objekt mit DeploymentName mehr — das Deployment wird beim Erstellen des ChatClient angegeben. Die Message-Typen heißen jetzt SystemChatMessage, UserChatMessage und AssistantChatMessage statt ChatRequestSystemMessage und Co.
Streaming
Vorher:
await foreach (StreamingChatCompletionsUpdate update
in client.GetChatCompletionsStreaming(options))
{
if (!string.IsNullOrEmpty(update.ContentUpdate))
{
Console.Write(update.ContentUpdate);
}
}
Nachher:
await foreach (StreamingChatCompletionUpdate update
in chatClient.CompleteChatStreamingAsync(messages))
{
foreach (ChatMessageContentPart part in update.ContentUpdate)
{
Console.Write(part.Text);
}
}
Subtiler, aber wichtiger Unterschied: In 2.x ist ContentUpdate eine Collection von ChatMessageContentPart-Objekten, nicht mehr ein einfacher String. Das liegt daran, dass Nachrichten jetzt multimodal sein können — Text, Bilder und Tool-Aufrufe kommen als separate Parts.
Tool Definitions (Function Calling)
Vorher:
var getWeatherTool = new ChatCompletionsFunctionToolDefinition()
{
Name = "get_current_weather",
Description = "Aktuelles Wetter für einen Ort abfragen",
Parameters = BinaryData.FromObjectAsJson(
new
{
Type = "object",
Properties = new
{
Location = new
{
Type = "string",
Description = "Stadt und Land, z.B. Berlin, DE",
}
},
Required = new[] { "location" },
},
new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
}),
};
Nachher:
ChatTool getWeatherTool = ChatTool.CreateFunctionTool(
"get_current_weather",
"Aktuelles Wetter für einen Ort abfragen",
BinaryData.FromObjectAsJson(
new
{
Type = "object",
Properties = new
{
Location = new
{
Type = "string",
Description = "Stadt und Land, z.B. Berlin, DE",
}
},
Required = new[] { "location" },
},
new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
}));
Die Factory-Methode ChatTool.CreateFunctionTool() ersetzt das explizite Instanziieren von ChatCompletionsFunctionToolDefinition. Weniger Boilerplate, gleiche Funktionalität.
Embeddings
Vorher:
EmbeddingsOptions options = new()
{
DeploymentName = "text-embedding-ada-002",
Input = { "Dein Text hier" },
};
Response<Embeddings> response = await client.GetEmbeddingsAsync(options);
EmbeddingItem item = response.Value.Data[0];
ReadOnlyMemory<float> vector = item.Embedding;
Nachher:
EmbeddingClient embeddingClient =
azureClient.GetEmbeddingClient("text-embedding-3-small");
OpenAIEmbedding embedding =
await embeddingClient.GenerateEmbeddingAsync("Dein Text hier");
ReadOnlyMemory<float> vector = embedding.ToFloats();
Gleiches Muster: szenario-spezifischer Client, weniger Boilerplate, klarere API.
Was bricht, wenn v2-SDK-Samples gegen ein Classic-Portal laufen
Wer ein v2-SDK-Beispiel gegen ein Classic-Portal laufen lässt — oder umgekehrt ein v1-Beispiel gegen das neue Foundry-Portal — wird schnell auf Probleme stoßen. Hier die häufigsten Stolperfallen:
| Symptom | Ursache | Lösung |
|---|---|---|
| Unerwartetes API-Verhalten oder fehlende Methoden | SDK-Version passt nicht zum Portal | SDK-Version prüfen: 1.x → Classic, 2.x → Foundry |
| Endpoint-Verbindungsfehler | Alte Multi-Endpoint-URLs lösen nicht mehr auf | Auf neues Single-Endpoint-Format umstellen: https://<project>.services.ai.azure.com |
AuthenticationError mit neuem Client | API Key ohne korrekten Header verwendet | DefaultAzureCredential mit Bearer Token Provider verwenden |
Agent-Code gibt 404 oder MethodNotAllowed | Assistants-API-Aufrufe gegen Responses-API-Endpoint | Agent-Code auf Responses API umschreiben |
| Projekte fehlen im neuen Portal | Hub-basierte Projekte sind im neuen Portal nicht sichtbar | Zum Classic-Portal wechseln oder zu Foundry-Projekten migrieren |
Die Kernregel: SDK-Version und Portal-Erfahrung müssen zusammenpassen. Azure.AI.Projects 1.x funktioniert nur mit dem Classic-Portal. Version 2.x funktioniert nur mit dem neuen Foundry-Portal. Mischt man das, bekommt man kryptische Fehler, die einen halben Tag kosten können.
Checkliste: Diese 5 NuGet-Pakete müssen ersetzt werden
Hier ist die konkrete Liste der NuGet-Pakete, die Migration brauchen. Ich empfehle, das nicht aufzuschieben — die Deadlines sind real.
1. Azure.AI.OpenAI 1.0 Beta → 2.x
Deadline: Jetzt. Die 1.0-Beta wird nicht weiterentwickelt.
<!-- Vorher -->
<PackageReference Include="Azure.AI.OpenAI" Version="1.0.0-beta.*" />
<!-- Nachher -->
<PackageReference Include="Azure.AI.OpenAI" Version="2.*" />
Das ist die Migration, die die meisten betrifft. Die gesamte API-Oberfläche hat sich geändert — Client-Konfiguration, Message-Typen, Response-Handling. Plant einen halben bis ganzen Tag pro Service ein, der das SDK nutzt.
2. Azure.AI.Inference → OpenAI NuGet-Paket
Deadline: 30. Mai 2026 (offiziell angekündigt)
<!-- Vorher -->
<PackageReference Include="Azure.AI.Inference" Version="*" />
<!-- Nachher -->
<PackageReference Include="OpenAI" Version="2.*" />
Azure.AI.Inference wird komplett eingestellt. Die Funktionalität geht in das Standard-OpenAI-NuGet-Paket über. Azure-spezifische Funktionalität kommt über Azure.AI.OpenAI als Erweiterung dazu.
3. Azure.AI.Projects 1.x → 2.x
Deadline: Beim Wechsel zum neuen Foundry-Portal.
<!-- Vorher -->
<PackageReference Include="Azure.AI.Projects" Version="1.0.0-beta.*" />
<!-- Nachher -->
<PackageReference Include="Azure.AI.Projects" Version="2.0.0-beta.*" />
Version 1.x zielt auf das Classic-Portal, 2.x auf das neue Foundry-Portal. Die 2.x-Linie bringt massive Breaking Changes mit: AIDeployment wird zu AssetDeployment, der AIProjectClient-Konstruktor unterstützt AuthenticationTokenProvider, und der GetOpenAIClient-Zugang wurde konsolidiert. Hier muss man die Solution einmal komplett durchgehen.
4. Azure.AI.Agents.Persistent → Responses API Patterns
Deadline: August 2026 (Assistants API Sunset)
Das Agent-SDK entwickelt sich aktiv weiter. Die aktuellen Beta-Versionen bringen Streaming MCP Tool-Support, AOT-Kompatibilität und Delta-Tool-Call-Modelle. Wer Agents nutzt, muss seinen Code auf die Responses API umstellen — dazu gleich mehr.
5. Azure.Identity → aktualisieren auf 1.16+
Deadline: So bald wie möglich.
<!-- Aktualisieren auf -->
<PackageReference Include="Azure.Identity" Version="1.16.*" />
Die neuen Versionen bringen verbesserte Claims-Challenge-Exceptions, reduzierten Probe-Traffic mit Managed Identity und Custom-Environment-Variable-Konstruktoren. Da DefaultAzureCredential jetzt der Standard für die Authentifizierung ist, will man hier unbedingt auf dem neuesten Stand sein.
Von der Assistants API zur Responses API
Das ist die Migration, die am meisten Arbeit macht — besonders für alle, die Agents mit Threads, Runs und Messages gebaut haben.
Die Konzepte mappen wie folgt:
| Assistants API (alt) | Responses API (neu) | Anmerkung |
|---|---|---|
| Assistants / Agents | Agent Versions | Versioniert, mit explizitem kind |
| Threads | Conversations | Speichern Items, nicht nur Messages |
| Messages | Items | Items sind eine Obermenge von Messages |
| Runs (async, gepollt) | Responses (sync per Default) | Kein Polling-Loop mehr nötig |
create_agent() | create_version() | Nutzt PromptAgentDefinition |
Was das in der Praxis bedeutet
Der größte Gewinn: Kein Polling mehr. Die Assistants API erforderte es, einen Run zu starten und dann in einer Schleife zu pollen, bis er fertig war. Wer das mal in Produktion hatte, kennt die Probleme — Race Conditions, Timeouts, verschluckte Fehler. Die Responses API ist synchron per Default. Man schickt eine Anfrage und bekommt eine Antwort.
Konzeptionell denkt man nicht mehr in “Ich erstelle einen Assistant, öffne einen Thread, sende eine Message, starte einen Run und warte auf das Ergebnis.” Stattdessen: “Ich erstelle eine Agent Version, arbeite mit Conversations und Items, und bekomme Responses.”
Conversations sind dabei mächtiger als die alten Threads — sie speichern nicht nur Nachrichten, sondern auch Tool-Aufrufe, Tool-Outputs und andere Interaktionen als Items.
Für bestehenden Agent-Code
- Polling-Loops entfernen — die Responses API ist synchron
- Thread-Management ersetzen durch Conversations
- Message-Handling umstellen auf Items (die mehr als nur Text enthalten können)
create_agent()ersetzen durchcreate_version()mitPromptAgentDefinition- Region prüfen — die Responses API ist nicht in allen Azure-Regionen verfügbar
Punkt 5 wird gerne übersehen: Wenn eure Foundry Resource in einer Region liegt, die die Responses API nicht unterstützt, müsst ihr eine neue Resource in einer unterstützten Region erstellen. Prüft das vor der Migration, nicht hinterher.
Mein Migrationsfahrplan
Wer jetzt startet, hat genug Zeit. Wer wartet, bekommt Zeitdruck. Hier ist mein empfohlener Ablauf:
- Sofort:
Azure.AI.OpenAIvon 1.0 Beta auf 2.x aktualisieren. Das ist die Basis für alles andere. - Q1 2026:
Azure.AI.Inferencedurch dasOpenAI-NuGet-Paket ersetzen. Deadline Mai 2026 — aber lieber früher als später. - Q1 2026:
Azure.AI.Projectsauf 2.x aktualisieren, wenn ihr zum neuen Foundry-Portal wechselt. - Q2 2026: Agent-Code von Assistants API auf Responses API migrieren. Deadline August 2026, aber das ist die aufwändigste Migration.
- Laufend:
Azure.IdentityundAzure.Coreaktuell halten.
Die SDK-Landschaft stabilisiert sich gerade. Die REST API unter /openai/v1/ hat GA erreicht, die SDK-Pakete werden folgen. Je früher man migriert, desto weniger technische Schulden akkumuliert man — und desto weniger Überraschungen gibt es, wenn die Deadlines näher rücken.
Wer bis Mai 2026 wartet und dann merkt, dass die Migration seines Agent-Codes auch noch ansteht — der hat ein Problem. Fangt jetzt an.
Weiterführende Ressourcen:
- Migrate from the Foundry (classic) portal — die zentrale Migrationsseite mit Terminologie-Mapping und Deadlines
- How to migrate from Azure.AI.OpenAI 1.0 Beta to 2.0 — der offizielle .NET-Migrationsguide mit weiteren Code-Beispielen

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.