Mistral Responses API:Large 4の設定とOpenAIからの移行

Mistral Large 4への最初のリクエストから、OpenAI Responsesの既存実装をステートレスなMistral APIへ移行する手順まで説明します。使用できないパラメーター、モデル別の推論設定、履歴全体の再送、関数の実行結果、入力トークン数を確認します。保存済みの会話の継続やサーバー側のツールが必要なら、Conversations APIを検討します。

目次
Mistral Responses API:Large 4の設定とOpenAIからの移行

Mistral Responses APIではmistral-large-4を使い、毎回のリクエストで会話履歴をinputに含めて送ります。サーバー側で会話を継続するパラメーターを外し、保存を無効にして、モデルが対応する推論の強度を選んでください。2026-11-01時点で、MistralのResponses APIはパブリックプレビューです。

Mistral Large 4への最初のリクエストを実行する

最初はMistralの現行Python SDKとMistralのAPIキーを使います。既存のResponsesクライアントを変更する前に、公式ドキュメントに沿ったリクエストから始めてください。

Python 3.10以降が必要です。Studio → API keysでキーを作成し、次のコマンドをBashで実行します。readが入力待ちになったら、キーを貼り付けてEnterを押してください。入力したキーは画面に表示されません。

python3 -m pip install -U mistralai
read -rs MISTRAL_API_KEY && export MISTRAL_API_KEY

次のコードをmistral_responses.pyとして保存します。補助関数によって、この後の例でも同じ指示とリクエスト設定を使えます。

import os
from mistralai.client import Mistral

client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
MODEL = "mistral-large-4"
INSTRUCTIONS = "Answer concisely."

def create_response(history, **options):
    result = client.responses.create(
        model=MODEL,
        input=history,
        instructions=INSTRUCTIONS,
        reasoning={"effort": "high"},
        max_output_tokens=4096,
        additional_properties={
            "store": False,
            "background": False,
            "truncation": "disabled",
        },
        **options,
    )
    if result.status != "completed":
        raise RuntimeError(
            f"{result.status}: {result.error or result.incomplete_details}"
        )
    return result

def answer_text(result):
    return "".join(
        part.text
        for item in result.output if item.type == "message"
        for part in item.content if part.type == "output_text"
    )

history = [{"role": "user", "content": "Explain a stateless API in one sentence."}]
response = create_response(history)
print(response.status)
print(answer_text(response))

同じBashセッションから実行してください。

python3 mistral_responses.py

この例では、completedに続いて空ではない説明文が表示されれば成功です。回答の文言は変わることがあります。

outputには推論や関数呼び出しも含まれます。answer_textは、その中のmessage要素からoutput_textを取り出して連結します。補助関数はcompleted以外なら、errorまたはincomplete_detailsを含む例外で停止します。

HTTPエンドポイントはhttps://api.mistral.ai/v1/responsesです。HTTPを直接送る場合は、Authorization: Bearer $MISTRAL_API_KEYヘッダーを使います。/responsesを自動で追加するクライアントでは、ベースURLをhttps://api.mistral.ai/v1に設定してください。

残りのPython例は、このファイルの変数と補助関数を再利用します。必要な例をファイルの末尾に追加してください。ファイルを再実行すると、追加した生成処理もすべて実行されます。

OpenAI Responsesのどのパラメーターを変更するか

OpenAI Responsesのリクエストを流用する前に、HTTPで送るJSONの各フィールドを次の条件に合わせます。MistralのResponses APIリファレンスに記載された、2026-11-01時点の条件です。

ResponsesリクエストのパラメーターMistralの条件移行時の対応
previous_response_id省略するか、nullを送ります。過去の出力要素をinputに含めて再送します。
conversation省略するか、nullを送ります。アプリ側で会話履歴を保持します。
store省略するか、falseまたはnullを送ります。trueを外し、保存済みのレスポンスに依存しない構成にします。
backgroundfalseが必須です。既定値もfalseです。バックグラウンド実行と、その状態を取得するポーリング処理を外します。
truncation"disabled"が必須です。既定値も同じです。送信前にコンテキストの大きさを調整します。
prompt省略するか、nullを送ります。プロンプトの内容をinputとinstructionsに入れます。
moderation省略するか、nullを送ります。この互換用フィールドに設定した値を外します。
top_logprobs省略するか、0またはnullを送ります。正の値を外します。
max_tool_calls受理されますが、現在は無視されます。アプリ側で実行回数の上限を設けます。
reasoning.effort選択したモデルが対応する値を使います。後述するモデル別の値を選びます。
toolsクライアント側で実行する関数を指定します。名前空間でのグループ化も可能です。プロバイダー側で実行するツールへの依存を置き換えます。
max_output_tokens推論トークンと回答本文の両方を含みます。両方に足りる出力トークン枠を確保します。

Python SDKのキーワード引数は、すべてのHTTPフィールドに直接対応しているわけではありません。現在のResponses実装では、store、background、truncationをadditional_properties経由で渡します。最初の例もこの方法を使っています。

プロバイダーごとの設定に、この違いを反映してください。エンドポイントの変更だけでは、各ツール、会話の継続方法、ストリーミングの処理まで互換であるとは確認できません。Messages、Chat Completions、Responsesの互換性ガイドでは、関数呼び出しの往復全体を確認する理由を説明しています。

使えるモデルと機能を確認する

この手順ではmistral-large-4を使い、モデルを変更する際には対応機能を確認し直してください。Mistralの公開時の発表では、Large 4を含め、同社がホストするすべてのチャットモデルに対応すると説明しています。

対応機能の一覧には、テキストの入出力、構造化出力、ストリーミング、関数呼び出し、モデルに応じた推論機能があります。画像入力には画像を扱えるモデルが必要で、画像URLまたはbase64のデータURLを使えます。ファイル入力にはHTTPS URL、base64のデータURL、アップロード済みファイルのIDを使えますが、対応状況はモデルによって異なります。

構造化出力では、text.formatでJSONモードまたはJSON Schemaを指定します。関数ツールを実行するのはアプリです。公開されている実装はクライアント側で実行する関数だけに対応するため、ホスト型のweb_searchをそのまま移すことはできません。

推論の強度は、Responsesの入れ子になったフィールドreasoning.effortで指定します。次の値は、2026-11-01に確認したMistralの推論ガイドに基づきます。

モデル対応する値選び方
mistral-large-4 / mistral-large-4-0low、medium、high例ではhighから始めます。応答時間やトークン消費が重要なら、低い設定と比較します。
mistral-small-2603none、high推論モードが必要ならhighを使います。
mistral-medium-3-5none、high既存の連携向けです。このモデルは非推奨です。

Large 4ではnone、minimal、xhigh、maxは使えません。初期のLarge 4プレビューの例を使っている場合は、noneをlowに変更してください。SDK共通の列挙型に値が存在しても、すべてのモデルがその値に対応するとは限りません。

Large 4のモデルカードにも、パブリックプレビューと記載されています。Medium 3.5のモデルカードでは、非推奨となった日を2026-10-31としています。新しい連携にはLarge 4を使うよう推奨しています。

複数ターンの入力を組み立て、関数の結果を返す

推論や関数呼び出しを含め、すべての要素の履歴を保持してください。回答本文は画面表示には使えますが、会話全体の記録にはなりません。

会話を続ける

前回のoutputに含まれるすべての要素を追加し、その後に次のユーザーメッセージを追加します。最初の例の後に、次のコードを置いてください。

history.extend(response.output)
history.append({"role": "user", "content": "What must the client send next time?"})
response = create_response(history)
print(answer_text(response))
history.extend(response.output)

二度目のリクエストには、最初のユーザーメッセージ、最初のレスポンス全体、続きの質問が含まれます。補助関数はinstructionsも毎回送ります。

これが、previous_response_idの代わりに使う、ドキュメントで示された方法です。レスポンスIDだけを保持しても、このステートレスなエンドポイントには履歴を渡せません。表示した回答本文だけを残すと、それ以外の返却要素が失われます。

関数の実行結果を返す

関数をローカルで実行し、対応するcall_idとともに結果を返してください。Mistralの関数呼び出しの例では、type、name、description、parametersを同じツールオブジェクトに置いています。次の例はその構造を使い、別の履歴を用意して、ローカルで加算を行います。

import json

TOOLS = [{
    "type": "function",
    "name": "add",
    "description": "Add two integers.",
    "parameters": {
        "type": "object",
        "properties": {
            "a": {"type": "integer"},
            "b": {"type": "integer"},
        },
        "required": ["a", "b"],
        "additionalProperties": False,
    },
}]
tool_history = [{"role": "user", "content": "Use add to calculate 19 + 23."}]
response = create_response(
    tool_history,
    tools=TOOLS,
    tool_choice={"type": "function", "name": "add"},
    parallel_tool_calls=False,
)
tool_history.extend(response.output)

calls = [item for item in response.output if item.type == "function_call"]
if len(calls) != 1 or calls[0].name != "add":
    raise RuntimeError("Expected exactly one add call.")

call = calls[0]
args = json.loads(call.arguments)
if (
    not isinstance(args, dict)
    or set(args) != {"a", "b"}
    or any(type(args[name]) is not int for name in ("a", "b"))
):
    raise ValueError("Expected two integer arguments.")

result = args["a"] + args["b"]
print("Local result:", result)
tool_history.append({
    "type": "function_call_output",
    "call_id": call.call_id,
    "output": json.dumps({"result": result}),
})
response = create_response(
    tool_history,
    tools=TOOLS,
    tool_choice="none",
    parallel_tool_calls=False,
)
print(answer_text(response))
tool_history.extend(response.output)

この例では、返された関数呼び出しが一つで、名前がaddであることを確認します。想定と違う呼び出しは実行せず、例外で停止します。

モデルが指定した引数をJSONとして読み取り、二つの整数であることも検証します。加算そのものはPythonが行い、結果をfunction_call_outputとしてモデルに返します。

Local result: 42が表示され、その後の回答がこの結果を使っていることを確認します。モデルが生成する文言は変わることがあります。

最初のリクエストはaddの呼び出しを必須にします。二度目はAPIリファレンスに従い、"none"で追加の呼び出しを無効にします。この例は、二度の生成処理と一度のローカル実行で完了する構成です。

終了までの回数が決まらないエージェントのループでは、反復回数と実行回数の上限をアプリ側で設けてください。max_tool_callsは無視されるため、上限の制御には使えません。

関数の結果を追加する前に、返された出力全体を履歴に保存します。結果を対応付けるのはcall_idであり、出力要素のidではありません。複数の関数呼び出しを許可する場合は、それぞれを検証し、すべての結果を返してから次のレスポンスを要求してください。

履歴が増える前に入力トークンを数える

履歴、指示、ツール定義を含め、次に送るリクエスト全体のトークンを数えてください。最新のユーザーメッセージだけでは、アプリが再送する内容を数え落とします。

関数の例の後に、次のコードを追加します。

next_input = tool_history + [
    {"role": "user", "content": "Explain that calculation in one sentence."}
]
count = client.responses.count_input_tokens(
    model=MODEL,
    input=next_input,
    instructions=INSTRUCTIONS,
    tools=TOOLS,
    reasoning={"effort": "high"},
    parallel_tool_calls=False,
    tool_choice="auto",
)
print(count.input_tokens)

このコードはPOST /v1/responses/input_tokensを呼び出し、input_tokensを表示します。回答を生成せず、入力のトークン数だけを数えます。その後に生成する際も、同じモデル、入力、指示、ツールを使ってください。

得られた数を選択したモデルのコンテキストウィンドウと比較し、出力に必要な余裕を残します。truncationは"disabled"のままにする必要があるため、いつ履歴を減らすかはアプリが判断します。

履歴を整理する際は、関数呼び出しと対応する結果を組にして保持してください。ツールとのやり取りの途中から、任意の要素だけを削除しないようにします。

トークン数だけでは金額の見積もりにはなりません。会話を繰り返した場合の費用やキャッシュの影響は、Mistral APIの最新料金を参照して計算してください。

移行時の不具合を切り分ける

まずリクエスト設定を確認し、次にステータスと出力要素を調べます。すべてを順番に試すのではなく、症状に合う項目を確認してください。

  • 送信前にSDKがキーワード引数を拒否します。 インストール済みSDKとメソッドの引数定義を確認します。ここで使うSDKでは、store、background、truncationをadditional_propertiesの中に入れます。
  • APIがリクエストを拒否します。 最初のテキストの例に戻してください。モデルID、対応する推論の強度、互換性の表を確認します。成功したら、任意のフィールドを一つずつ戻します。
  • モデルが前の会話を忘れます。 次のinput配列を確認してください。レスポンスIDだけでなく、以前のメッセージと出力要素全体が必要です。
  • 回答本文がありません。 status、error、incomplete_detailsを確認します。実行待ちの関数呼び出しがないかも調べてください。生成が出力上限に達していた場合は、上限を増やすか、対応範囲内で推論の強度を下げます。
  • リクエストが誤ったパスに届きます。 最終的なURLをhttps://api.mistral.ai/v1/responsesと比較します。ベースURLとエンドポイントのトラブルシューティングガイドでは、パスを組み立てる際のよくある誤りを説明しています。

ストリーミングではstream=Trueを指定し、Responsesのイベントを処理します。公式のPythonストリーミング例では、各イベントをframe.dataから読み取ります。回答本文はresponse.output_text.deltaで届き、完了はresponse.completedで通知されます。

response.failed、response.incomplete、errorも処理してください。テキストの一部が届いただけでは、正常終了したとは判断できません。バックグラウンド生成は無効なので、この構成にポーリング用のループは不要です。

Responses、Chat Completions、Conversationsを使い分ける

要素単位の形式がアプリに合い、履歴と関数実行を自分で管理したい場合は、Responsesを選びます。

アプリに必要なもの最初に選ぶAPI理由
Responses形式の入出力要素とストリーミングイベントResponses APIその形式を使いながら、状態と関数をアプリ側で管理できます。
メッセージ形式を使う既存の連携Chat Completionsメッセージを中心としたリクエストとレスポンスの処理を維持できます。
保存済みの会話の継続、またはMistral側で実行するツールConversations API会話IDと、サーバー側のツール用の別インターフェースを利用できます。

MistralのChat Completionsガイドでは、メッセージ形式を説明しています。Conversationsリファレンスでは、conversation_idを使った継続方法を確認できます。

Mistral側で行う検索については、ConversationsとAgentsの説明にweb_searchとweb_search_premiumがあります。この機能は、Responsesでクライアント側が実行する関数ツールとは別です。

現在のアプリが保存済みの会話やサーバー側のツールに依存するなら、リクエストの内容を移す前にConversationsを検討してください。履歴と関数をすでにアプリ側で管理しているなら、テキストのリクエスト、次の会話、関数呼び出しの往復を確認します。その後で、エージェント全体を接続してください。

LLM ワークフローを最適化しませんか?

単一 API でモデルを接続し、キーと AI コストを管理できます。

無料で始める