Semantic Kernel × Azure AI Foundry 推論APIで突然401 Unauthorizedになる原因と対処法

Semantic Kernel から Azure AI Foundry(Azure AI Inference)を呼び出しているアプリが、コードを一切変更していないのに突然「401 Unauthorized」になった──本記事では、この現象の正体と、models エンドポイント・認証方式・設定の見直しによって確実に復旧させるための具体的な手順を詳しく解説します。

目次

症状の整理:Semantic Kernel のコードは変えていないのに 401 が出る

まずは、実際によくある状況を整理します。

  • Semantic Kernel の .NET 版(Microsoft.SemanticKernel)を利用
  • Azure AI Foundry 向けコネクタとして Microsoft.SemanticKernel.Connectors.AzureAIInference を使用
  • チャット(Chat Completion)や埋め込み(Embeddings)を問題なく呼べていた
  • ある日を境に、コードを変更していないのに すべての呼び出しが 401 Unauthorized に

典型的な例外メッセージは次のようなものです。

Azure.RequestFailedException: 
Status: 401 (Unauthorized)

Content:
{"error":{"code":"Unauthorized","message":
"Access token is missing, invalid, audience is incorrect (https://ai.azure.com), or have expired."}}

さらに、次のような共通点があります。

  • Semantic Kernel 側のコードは変更していない
  • Azure AI Foundry の「プロジェクト URL(ai.azure.com の URL)」をそのまま endpoint に設定していた
  • 最小構成の検証コンソールアプリを作っても、同じ 401 が再現する

「先週まで https://ai.azure.com/... なプロジェクト URL を endpoint に入れても動いていたのに、なぜ急にダメになったの?」という疑問につながるわけです。

結論:プロジェクト URL ではなく「models エンドポイント」を使う

先に結論をはっきりさせます。

Semantic Kernel × Azure AI Foundry 推論 API で 401 が出た原因の多くは、endpoint に https://ai.azure.com/... の「プロジェクト URL」を指定していることです。

正しくは、Azure AI Foundry リソースに対して提供されている Azure AI Inference の models エンドポイントを指定します。

https://<resource-name>.services.ai.azure.com/models

Microsoft の公式ドキュメントでも、Foundry の推論用エンドポイントとして https://<resource-name>.services.ai.azure.com/models 形式の URL を使用することが明示されています。

混同しがちな URL の役割を整理しておきましょう。

種類URL の例主な用途Semantic Kernel から推論に使ってよいか
ポータル / プロジェクト URLhttps://ai.azure.com/projects/...ブラウザでの管理画面、ノートブック、評価 UI など× 使わない
プロジェクト管理 APIhttps://<resource>.services.ai.azure.com/api/projects/...エージェントやツールの一覧取得など「プロジェクトの管理」APIチャット/埋め込み推論には使わない
Azure AI Inference
models エンドポイント
https://<resource>.services.ai.azure.com/modelsチャット、埋め込みなど 推論 API の着地点◎ ここを使う
Azure OpenAI エンドポイントhttps://<resource>.openai.azure.comAzure OpenAI 資源用(Foundry 経由で使うケースもあり)Azure OpenAI コネクタ時のみ

Semantic Kernel の Azure AI Inference コネクタは、「models エンドポイント」+「モデル ID」を前提に設計されています。

実装例:C# / Semantic Kernel から Azure AI Foundry 推論 API を呼び出す

前提:必要な NuGet パッケージ

Semantic Kernel で Azure AI Inference を使うには、最低限次のパッケージをインストールします。

dotnet add package Microsoft.SemanticKernel
dotnet add package Microsoft.SemanticKernel.Connectors.AzureAIInference --prerelease

公式ドキュメント上でも、Azure AI Inference 用に Microsoft.SemanticKernel.Connectors.AzureAIInference パッケージが案内されています。

プロジェクト API キーでチャットを呼び出す場合(DI 拡張版)

まずは、プロジェクト API キー(Project Keys)を使ってチャットを呼び出すコード例です。

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;

class Program
{
    static async Task Main()
    {
        var services = new ServiceCollection();

        // Azure AI Inference (Azure AI Foundry) の models エンドポイントを指定
        services.AddAzureAIInferenceChatCompletion(
            modelId: "gpt-4.1",
            apiKey: "&lt;PROJECT_API_KEY&gt;", // Azure AI Foundry プロジェクトの API キー
            endpoint: new Uri("https://&lt;resource&gt;.services.ai.azure.com/models")
        );

        var provider = services.BuildServiceProvider();
        var chat = provider.GetRequiredService&lt;IChatCompletionService&gt;();

        var history = new ChatHistory();
        history.AddUserMessage("今日の東京の天気を簡単に教えて。");

        var result = await chat.GetChatMessageContentAsync(history);
        Console.WriteLine(result);
    }
}

ポイント

  • endpoint には 必ず https://<resource>.services.ai.azure.com/models を指定します。
  • <resource> には、Azure AI Foundry のリソース名(例: my-foundry)が入ります。
  • <PROJECT_API_KEY> には プロジェクトの API キー を設定します(別リソースのキーを使わない)。

Entra ID(DefaultAzureCredential)で認証する場合

Azure AD / Entra ID を使ってトークンベースで認証する場合も、endpoint さえ正しければ Semantic Kernel 側のコードはほとんど変わりません。

using Azure.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;

var services = new ServiceCollection();

// DefaultAzureCredential を利用したトークン認証
services.AddAzureAIInferenceChatCompletion(
    modelId: "gpt-4.1",
    credential: new DefaultAzureCredential(),
    endpoint: new Uri("https://&lt;resource&gt;.services.ai.azure.com/models")
);

var provider = services.BuildServiceProvider();
var chat = provider.GetRequiredService&lt;IChatCompletionService&gt;();

var history = new ChatHistory();
history.AddUserMessage("Semantic Kernel と Azure AI Foundry の違いを教えて。");

var result = await chat.GetChatMessageContentAsync(history);
Console.WriteLine(result);

Entra ID を使う場合、Azure AI Inference では scope として https://cognitiveservices.azure.com/.default が使われます(トークン生成を SDK に任せていれば自動で設定されます)。

埋め込み(ベクトル化)を呼び出すコード例

埋め込みモデルを Semantic Kernel で利用する場合も、基本的な考え方はチャットと同じです。

using Microsoft.Extensions.DependencyInjection;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Embeddings;

var services = new ServiceCollection();

services.AddAzureAIInferenceTextEmbeddingGeneration(
    modelId: "text-embedding-3-large",
    apiKey: "&lt;PROJECT_API_KEY&gt;",
    endpoint: new Uri("https://&lt;resource&gt;.services.ai.azure.com/models")
);

var provider = services.BuildServiceProvider();
var embeddingService =
    provider.GetRequiredService&lt;ITextEmbeddingGenerationService&gt;();

var text = "Vector search 用にベクトル化したい文章です。";
var embedding = await embeddingService.GenerateEmbeddingAsync(text);

Console.WriteLine($"Embedding length: {embedding.Length}");

ここでも endpoint はチャットと同じ .../models で共通化できるのがポイントです。

構成ファイル(appsettings.json)でモデルとエンドポイントを管理する例

複数モデルを切り替えたい場合は、エンドポイントは固定にして、モデル ID だけを設定ファイルから差し替える運用にすると非常に扱いやすくなります。

{
  "AzureAI": {
    "Endpoint": "https://&lt;resource&gt;.services.ai.azure.com/models",
    "ProjectApiKey": "&lt;PROJECT_API_KEY&gt;",
    "ChatModelId": "gpt-4.1",
    "EmbeddingModelId": "text-embedding-3-large"
  }
}

DI 登録側では、この設定を読み込んでそれぞれのサービスを登録するだけです。

var config = builder.Configuration.GetSection("AzureAI");

services.AddAzureAIInferenceChatCompletion(
    modelId: config["ChatModelId"],
    apiKey: config["ProjectApiKey"],
    endpoint: new Uri(config["Endpoint"]!)
);

services.AddAzureAIInferenceTextEmbeddingGeneration(
    modelId: config["EmbeddingModelId"],
    apiKey: config["ProjectApiKey"],
    endpoint: new Uri(config["Endpoint"]!)
);

なぜ今になって 401 Unauthorized が出るのか

「今までたまたま動いていたものが、ある日突然 401 になった」というパターンの多くは、仕様の明確化や認証チェックの厳格化が背景にあります。

プロジェクト URL は「管理用」、推論 API の着地点ではない

Azure AI Foundry では、ポータルや管理機能用のエンドポイントと、推論用のエンドポイントが別々に用意されています。

  • プロジェクト URL(ai.azure.com):ブラウザや管理用 API からプロジェクトを操作するための URL
  • Azure AI Inference models エンドポイント:モデルへ推論リクエストを送るための URL

Foundry の公式ドキュメントでも、推論には https://<resource>.services.ai.azure.com/models を使用し、/models/chat/completions や /models/embeddings などのルートで各機能にアクセスすることが示されています。

一方で Semantic Kernel の Azure AI Inference コネクタは、「推論 URL」だけを受け取る設計です。つまり、ai.azure.com のプロジェクト URL を渡してしまうと、そもそも「期待している API ではない URL」に対してトークンやキーを投げている状態になります。

audience 不一致による 401 のイメージ

Entra ID(旧 Azure AD)のトークンには、どのサービス向けのトークンなのかを示す aud(audience)クレームが含まれています。

  • トークンの aud は https://cognitiveservices.azure.com/ など
  • しかしアクセス先は https://ai.azure.com/... の管理エンドポイント

このように、「トークンの audience」と「実際にアクセスしているエンドポイント」が噛み合わないと、サーバー側は 「このトークンはこのサービス向けではない」と判断し、401 を返します。

逆に、models エンドポイントに対して、Azure AI Inference SDK や Semantic Kernel コネクタが期待する形でトークンやキーを渡していれば、audience は正しく解釈され、401 は発生しません。

「以前は動いていた」理由の推測

詳細な内部仕様は公開されていませんが、次のような要因が組み合わさって「たまたま動いていた」状態だった可能性があります。

  • 初期は ai.azure.com 側の認証チェックが緩く、プロジェクト URL 宛のリクエストでも通ってしまっていた
  • 内部で models エンドポイントにフォワードされるなど、暫定的な実装が存在していた
  • 仕様変更やセキュリティ強化により、2024〜2025 年頃から audience のチェックが厳格化された

いずれにせよ、現在の公式な位置付けとしては「推論は models エンドポイントに送るのが前提」であり、Semantic Kernel でもそれを前提にコードを書くのが安全です。

モデル切り替えのベストプラクティス:エンドポイントは固定、modelId を変える

Azure AI Inference の models エンドポイントは、「同じエンドポイントで複数のデプロイ済みモデルを扱う」という設計になっています。リクエストの中で指定した model(もしくは name)に応じて、適切なデプロイメントへルーティングされます。

Semantic Kernel から見ると、次のような運用がシンプルです。

  • エンドポイント:https://<resource>.services.ai.azure.com/models で固定
  • 認証情報:プロジェクト API キー or Entra ID トークンで固定
  • モデル ID:gpt-4.1 / gpt-4o-mini / text-embedding-3-large などを差し替え

構成イメージを表にすると次のようになります。

用途設定値例
エンドポイント共通https://<resource>.services.ai.azure.com/models
認証共通プロジェクト API キー or DefaultAzureCredential
Chat モデルmodelIdgpt-4.1 / gpt-4o-mini など
Embedding モデルmodelIdtext-embedding-3-large など

アプリ側では modelId を設定ファイルや環境変数で切り替えるだけで、複数モデルを簡単に使い分けることができます。

401 Unauthorized をつぶすチェックリスト

最後に、実際にトラブルシューティングする際のチェックポイントを一覧化しておきます。

項目チェック内容よくある落とし穴 / 対処
エンドポイントhttps://<resource>.services.ai.azure.com/models を使っているか?https://ai.azure.com/... を渡していないか再確認 コピー時に /models を落としていないか
キーの種類Azure AI Foundry プロジェクトの Project API Key を使っているか?別リソース(Azure OpenAI や Azure AI Services)のキーを混同していないか キー再生成後、アプリ設定を更新し忘れていないか
Entra ID トークンDefaultAzureCredential など SDK 任せにしているか? 自前でトークン発行する場合、scope / audience が正しいか?scope は https://cognitiveservices.azure.com/.default を利用 リソースに対する「所有者 / 共同作成者 / 読み取り」等の権限が不足していないか
モデル IDFoundry 上のデプロイ名やモデル名と一致しているか?古いモデル名(例:text-embedding-ada-002)をそのまま使っていないか ポータル側でデプロイを削除していないか
ネットワークプロキシやファイアウォールで services.ai.azure.com への outbound が許可されているか?企業ネットワークや VNet 経由の場合はネットワークチームに確認 一度ローカル PC から curl / Postman で疎通確認する
システム時間アプリ実行環境の時計が大きくずれていないか?VM / コンテナのタイムゾーン・NTP 設定を確認 トークンが即時に期限切れと判定されるケースを防ぐ
SDK / Semantic Kernel のバージョンMicrosoft.SemanticKernel と ...Connectors.AzureAIInference を最新安定版にしているか?古いプリリース版では API 仕様が変わっていることがある Semantic Kernel のリリースノートに Breaking Change がないか確認

よくある質問(FAQ)

Q. 以前は ai.azure.com の URL でも動いていたのですが…

A. それは「たまたま動いていただけ」の可能性が高く、現在の仕様では 推論にプロジェクト URL を使うことはサポートされていません。今後の安定運用のためにも、必ず https://<resource>.services.ai.azure.com/models を使うようにしてください。

Q. Azure OpenAI のエンドポイントと何が違いますか?

A. Azure OpenAI 資源の場合は https://<resource>.openai.azure.com 形式のエンドポイントを使い、モデルごとに /openai/v1/chat/completions などのパスを叩きます。一方、Azure AI Foundry の Azure AI Inference では https://<resource>.services.ai.azure.com/models が共通エンドポイントとなり、その上に /models/chat/completions や /models/embeddings をぶら下げる形になります。

Q. プロジェクト API キーと、Azure ポータルの「キーとエンドポイント」は別物ですか?

A. Azure AI Foundry では、リソース全体に対するキーと、プロジェクト単位のキーが混在して見えることがあります。Semantic Kernel の Azure AI Inference コネクタで推論を行う場合は、対象となる Foundry リソース / プロジェクトに紐づいた API キーを使う必要があります。別リソースのキーを使うと、同じ 401 Unauthorized になります。

Q. SDK ではなく生 REST で呼ぶ場合も、やることは同じ?

A. はい、基本はまったく同じです。

  • URL:https://<resource>.services.ai.azure.com/models/chat/completions?api-version=...
  • ヘッダー:api-key または Authorization: Bearer <token>
  • ボディ:model にデプロイ名(例:"gpt-4.1")を指定

Semantic Kernel はこの REST API 呼び出しをラップしてくれているだけなので、根本原因と対処方針は同じと考えて問題ありません。

まとめ:models エンドポイントへ切り替えれば 401 は解消できる

本記事のポイントを改めて整理します。

  • Semantic Kernel × Azure AI Foundry で突然 401 Unauthorized が出た場合、ai.azure.com のプロジェクト URL を endpoint にしているパターンが非常に多い
  • 推論に使うべきは Azure AI Inference の models エンドポイント:
    • https://<resource>.services.ai.azure.com/models
  • 認証方式は
    • プロジェクト API キー
    • Entra ID(DefaultAzureCredential)
    のどちらかを正しく設定する
  • エンドポイントを正しく切り替えた上で、キー種別・scope・モデル ID・ネットワークなどをチェックリストで確認すれば、ほとんどの 401 は解消できる
  • 運用面では、エンドポイントは共通の models エンドポイントに固定し、modelId だけで Chat / Embedding を切り替える構成にしておくと管理が楽になる

「先週まで動いていたのに急に 401 になった…」という場合でも、この記事の方針通りに models エンドポイント + 正しい認証へ切り替えれば、再び安定して Semantic Kernel から Azure AI Foundry 推論 API を利用できるようになるはずです。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次