第5回 ClaudeをMicrosoft Foundryで使う — 思考ブロックと追記専用の会話設計

連載:LLMのAPIと提供経路を選ぶ・第5回 | 連載のまとめ

会話ごとのモデル選択

Microsoft Foundry(以下、Foundry)のClaudeでチャットアプリを作る場合、Claude Opus 5.5(以下、Opus 5.5)を詳しい分析、Claude Sonnet 5.5(以下、Sonnet 5.5)を低遅延の応答や補助処理に使う構成を提案します。会話を担当するモデルは開始時に決め、タイトル生成や分類は会話とは別の単発処理にします。

APIがモデルの切り替えを全面的に禁止しているという意味ではありません。思考ブロックの互換性と履歴の一貫性を守り、予期せぬ推論の欠落を避けるための設計判断です。

会話開始時にOpusかSonnetを選択し、チャットAPIが受け取ったcontent blocksを会話ストアへ追記する。Foundry認証はMicrosoft Entra ID、監視はAzure Monitorを使用。
筆者の事前調査を基にしたClaudeの構成例。会話単位でモデルを固定する方針を示します。図の「変更は途中systemメッセージで」は、対象機能の対応を確認した場合の選択肢です。

思考ブロックの保存と表示

Opus 5.5では思考が常時有効で、無効化や手動のbudget_tokens指定は受け付けられません。本文が空の思考ブロックが返る場合もあるため、content[0]を回答だと決めつけず、typeで区別します。[1]

Sonnet 5.5のbetween_toolsは前置きの思考を省く選択肢で、low・medium・highで使えます。xhigh・maxや追加のdisplayなどとの併用には制約があります。応答時間を短くする設定を採用するときは、品質も評価します。[2]

画面に表示する回答文と、次のリクエストへ再送するcontent配列は分けて扱います。content配列は、思考・署名・ツール関連の情報も含め、加工せずに保存します。画面に思考を表示しない場合も、履歴から削除するという意味ではありません。

履歴の追記と過去の質問の編集

思考ブロックは、どのモデルが、どの会話履歴から生成したかに結び付いています。過去のsystem・tools・メッセージを書き換えて再送すると、アカウント条件や設定に応じてエラーやブロックの破棄が起こる場合があります。[3]

そのため、利用者が過去の質問を修正したら、修正した地点から新しい会話として処理を始めます。これを会話の分岐として扱い、変更後の履歴へ古い思考ブロックをそのままコピーする設計は避けます。プロンプトを更新するときも、進行中の会話にどう適用するかと、新しい会話へ適用することを分けて考えます。

更新したいもの 初期の実装方針
ユーザーの過去発言 修正した地点から新しい会話として開始
systemやツール定義 既存会話では固定し、新規会話へ適用
推論の深さ・effort そのモデルとモードで許される変更だけ適用
会話の短縮 対応する圧縮機能を検証するか、要約から新しい会話として開始

会話途中のsystemメッセージ、ツール追加、メッセージ単位のeffort変更、圧縮は便利な選択肢ですが、ベータや提供経路の条件があります。初期実装の必須機能にせず、モデル・ホスティング・ソフトウェア開発キット(以下、SDK)で利用できることを確かめてから追加します。

モデル間で思考を引き継げる条件

直接APIやGoogle Cloudでは、Opus 5.5がSonnet 5.5の思考を読めるという条件付きの互換性も公式文書に記載されています。一方、Sonnet 5.5が他モデルの思考を読めるとは限りません。Foundryへこの互換性をそのまま当てはめることもできません。[1][2]

「Claude同士なら互換性がある」「モデルを切り替えると必ず全履歴が失われる」のどちらも、条件を十分に説明していません。利用者に見える発言と回答の履歴は渡せても、以前の推論が維持されない場合があります。会話を担当するモデルを固定するのは、この複雑さをアプリの利用者へ持ち込まないための方針です。

Foundryへの接続と応答の逐次表示

次はOpus用デプロイへ接続し、届いたテキストを順に表示する最小例です。依存パッケージはanthropicとazure-identity、環境変数にはFoundryのリソース名とデプロイ名を設定します。認証済みIDには、ロールベースのアクセス制御(RBAC)で必要な権限を割り当てます。[4]

import os
from anthropic import AnthropicFoundry
from azure.identity import DefaultAzureCredential, get_bearer_token_provider

token_provider = get_bearer_token_provider(
    DefaultAzureCredential(), "https://ai.azure.com/.default"
)
client = AnthropicFoundry(
    resource=os.environ["ANTHROPIC_FOUNDRY_RESOURCE"],
    azure_ad_token_provider=token_provider,
)
history = [{"role": "user", "content": "この設計の改善点を挙げてください。"}]
with client.messages.stream(
    model=os.environ["ANTHROPIC_FOUNDRY_OPUS_DEPLOYMENT"],
    max_tokens=8000,
    output_config={"effort": "medium"},
    messages=history,
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
    final = stream.get_final_message()

# 表示本文とは別に、全content blocksをJSONへ変換して保持する。
history.append({
    "role": "assistant",
    "content": [block.model_dump(mode="json") for block in final.content],
})
print("\n終了理由:", final.stop_reason)

この例は実APIで検証していません。永続保存、ツール実行、切断時の処理、拒否や上限到達に応じた処理は別途実装します。ツール待ちの応答をそのまま「完了」として扱わず、tool_useに対応するtool_resultを返して会話を続ける処理が必要です。使用するSDKのバージョンを固定し、保存・再読込で署名が失われないかをテストします。

終了理由に応じた拒否・障害の処理

stop_reasonを確認し、拒否、上限到達、ツール待ち、通常完了を分けて扱います。拒否を429や5xxの障害と同じように扱い、自動で別モデルへ処理を引き継ぐ設計にはしません。再試行してよい条件と利用者への案内を、業務方針に沿って決めます。

Foundryではサーバー側のfallbacksを使えないため、必要な代替処理はアプリ側に実装します。これはすべての拒否を回避するための仕組みではありません。障害時に再試行する場合も、ツールでどこまで操作を実行したかを確認し、同じ操作が重複しないようにします。

運用で記録する情報

FoundryではClaudeの標準レート制限ヘッダーが返らないため、Azure側の監視とアプリで記録する使用量を組み合わせます。Azure MarketplaceのCCUという単位での課金は、直接APIのドル単価をそのまま円換算した請求とは限りません。[4]

会話ID、デプロイ、実モデル、設定、使用量、終了理由、request-idとapim-request-idを記録すると調査しやすくなります。原文履歴はアクセスを制限し、運用メトリクスは本文を含めずに集計する方針を提案します。

第4回と共通の構成と、APIの違いで変える部分

第4回 OpenAIをMicrosoft Foundryで使う — Responses APIと2モデル構成の設計では、Azure App Serviceにチャット画面とアプリAPIを配置し、Azure Cosmos DB for NoSQLで会話を保存する例を示しました。Claudeでも、この基本構成を使えます。社内検索にAzure AI Searchや既存の検索APIを使い、Azure Monitorとアプリの記録で使用量・遅延・障害を調べる役割分担も共通です。

上の構成図では、チャットAPIの実行先としてAzure Container Appsを例示しています。ここでは第4回と対応づけるため、実行先をAzure App Serviceにそろえます。以下は、この連載のモデル選択・履歴管理の方針に基づく構成例です。

共通のAzure構成に加える変更

対象 第4回のOpenAI構成 本記事のClaude構成
モデルの接続先 Azure OpenAIの2デプロイをResponses APIで呼ぶ FoundryのOpus・SonnetのデプロイをMessages APIで呼ぶ。接続クライアントをAnthropicFoundryへ変更
呼び出すモデルの選択 処理に応じて振り分け、モデル切り替え時は必要な履歴と根拠を引き継ぐ 会話開始時に担当モデルを決め、タイトル生成や分類は別処理に分ける
会話ストア 発言と回答に加え、推論・ツールのアイテムも保存。応答IDを参照する方式も選べる messagesと応答のcontentブロックを、思考・署名・ツールの情報を含めて保存し、次のリクエストへ再送
履歴を編集する処理 別モデルへの引き継ぎや推論状態の互換性を確認する 追記を基本にし、過去の質問を修正した場合は、その地点から新しい会話として開始
応答を処理する部分 statusなどで完了・未完了を判定し、ツール実行も管理する contentのtypeで表示・保存を分け、stop_reasonで完了・上限・ツール待ち・拒否を判定する
監視の記録 使用量・終了状態・処理時間などをアプリで記録する 同じ監視基盤に、Claudeのusage、終了理由、request-id・apim-request-idを記録する。標準レート制限ヘッダーに依存した制御は使わない

第4回でも、自前の履歴を送る方式では推論・ツールの情報を保存する必要があります。Claudeで同じ会話ストアを使う場合も、保存するデータの形式と更新ルールを、Messages APIに合わせて設計します。特に思考ブロックを再送する構成では、過去のsystem・tools・messagesを毎回作り直して内容を変えないよう、会話開始時の定義と実際に送受信した履歴を保持します。[3]

接続設定と権限を置き換える

App Serviceのアプリ設定は、前段のPython例に対応させて次のようにします。<resource-name>はClaudeをデプロイしたFoundryリソースの名前です。Opus・Sonnetのデプロイ名は、作成したものに合わせます。[4]

ANTHROPIC_FOUNDRY_RESOURCE=<resource-name>
ANTHROPIC_FOUNDRY_OPUS_DEPLOYMENT=chat-opus-5-5
ANTHROPIC_FOUNDRY_SONNET_DEPLOYMENT=chat-sonnet-5-5

前段の最小コードはOpus用の設定を使います。Sonnet用の設定は、会話開始時のモデル選択や単発の補助処理を実装したアプリで使用します。第4回のOpenAI用の接続先やSDKをそのまま使うのではなく、FoundryのClaude向けリソース名・クライアント・デプロイ名を対応づけます。

マネージドIDを使う方針は第4回と共通ですが、モデルの呼び出し権限は接続先に合わせて割り当てます。Claudeの公式資料では、Foundryリソースを利用できるロールとしてFoundry UserやCognitive Services Userが挙げられています。第4回で例示したCognitive Services OpenAI Userをコピーするだけで、Claudeにも必要な権限が付くとは判断しません。Cosmos DBや社内検索への権限は、モデルの呼び出し権限とは別に設定します。[4]

アプリ側で確認する処理

配置後は、接続確認に加えて、会話ストアから読み戻したブロックを加工せず再送できるか、過去の質問の修正が別の会話として扱われるかを確認します。ツール待ちの場合は、アプリが実行結果を対応するtool_resultとして返し、モデルの応答を続けます。

Azure側の監視を共通化しても、終了判定や再試行はAPIごとに実装します。ClaudeのFoundryではサーバー側のfallbacksが非対応のため、必要な代替処理はアプリ側に置き、拒否・上限到達・一時障害を分けて扱います。会話ごとのモデル固定、履歴の保存・再送、終了理由の判定を組み合わせて、この構成を動かします。[4]

前回: 第4回 OpenAIをMicrosoft Foundryで使う — Responses APIと2モデル構成の設計

参考資料

参考資料の仕様確認日:2026年10月8日。構成比較で扱う接続・権限・履歴再送・監視の条件は、2026年10月26日に英語版の資料も追加確認しました。構成と保存方式は筆者の設計提案です。

  1. Opus 5.5の変更点(Anthropic)
  2. Sonnet 5.5の変更点(Anthropic)
  3. Preserved thinking(Anthropic)。構成比較の追記時には英語版も確認:思考ブロックを再利用できる条件と追記型の履歴管理。
  4. Foundry用SDKと認証(Anthropic)。構成比較の追記時には英語版も確認:接続・ロール、応答形式、監視・レート制限ヘッダー、非対応の機能。