Mistral Responses API: Large 4 Setup and OpenAI Migration

Start with a Mistral Large 4 request, then adapt an OpenAI Responses integration to Mistral's stateless contract. Check unsupported parameters, model-specific reasoning settings, complete history replay, function-result handling, and input token counting. Choose Conversations when you need stored continuation or hosted tools.

Contents
Mistral Responses API: Large 4 Setup and OpenAI Migration

Use the Mistral Responses API with mistral-large-4, and send conversation history in input on every request. Remove server-side continuation parameters, keep storage disabled, and choose a reasoning effort that the model accepts. As of 2026-11-01, Mistral’s Responses API is in public preview.

Run a minimal Mistral Large 4 request

Use the current Mistral Python SDK and a Mistral API key for the first request. This gives you a documented starting point before adapting an existing Responses client.

Use Python 3.10 or newer. Create a key under Studio → API keys, then run these commands in Bash. At the silent read, paste your key and press Enter.

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

Save the following code as mistral_responses.py. The helper keeps instructions and request settings consistent across the later examples.

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))

Run it from the same Bash session:

python3 mistral_responses.py

For this example, success means completed followed by a nonempty explanation. The wording can vary. The parser selects answer text because output can also contain reasoning and function calls.

The HTTP endpoint is https://api.mistral.ai/v1/responses. Raw HTTP requests use the Authorization: Bearer $MISTRAL_API_KEY header. A client that appends /responses needs the Base URL https://api.mistral.ai/v1.

The remaining Python examples reuse this file’s variables and helpers. Append the examples you need; rerunning the file executes all included generation calls.

Which OpenAI Responses parameters must change?

Apply these HTTP JSON requirements before reusing an OpenAI Responses request. Mistral’s Responses API reference defines the accepted values as of 2026-11-01.

Parameter in your Responses requestMistral requirementMigration action
previous_response_idOmit it or send null.Replay prior output items in input.
conversationOmit it or send null.Keep conversation history in your application.
storeOmit it, or send false or null.Remove true; do not depend on stored responses.
backgroundMust be false; its default is false.Remove background execution and its polling path.
truncationMust be "disabled"; this is also the default.Manage context size before sending the request.
promptOmit it or send null.Put prompt content in input and instructions.
moderationOmit it or send null.Remove a populated compatibility field.
top_logprobsOmit it, or send 0 or null.Remove a positive value.
max_tool_callsAccepted but currently ignored.Enforce execution limits in your application.
reasoning.effortMust match the selected model.Use the model-specific values below.
toolsClient-executed functions, optionally grouped into namespaces.Replace dependencies on provider-hosted tools.
max_output_tokensCovers reasoning tokens and answer text together.Leave enough output budget for both.

The Python SDK’s keyword arguments do not mirror every HTTP field. Its current Responses implementation accepts store, background, and truncation through additional_properties. The first example uses that route.

Keep these differences in your provider configuration. Changing an endpoint does not establish that every tool, continuation method, or streaming handler is compatible. The guide to Messages, Chat Completions, and Responses compatibility explains why a complete tool round trip matters.

Which models and features can you use?

Use mistral-large-4 for this walkthrough, then check capabilities when you change models. Mistral’s launch announcement describes support for all chat models it hosts, including Large 4.

The supported-features list includes text input and output, structured output, streaming, functions, and model-dependent reasoning. Image input requires a vision-capable model and accepts image URLs or base64 data URLs. File input accepts HTTPS URLs, base64 data URLs, or uploaded file IDs; support still depends on the model.

Structured output uses text.format for JSON mode or JSON Schema. Function tools run in your application. The published implementation supports client-executed functions only, so do not carry a hosted web_search tool into this request unchanged.

For reasoning, use the nested Responses field reasoning.effort. These settings follow Mistral’s Reasoning guide, checked on 2026-11-01:

ModelSupported effort valuesPractical choice
mistral-large-4 / mistral-large-4-0low, medium, highStart with high for the example. Compare lower settings when latency or token usage matters.
mistral-small-2603none, highUse high when you need its reasoning mode.
mistral-medium-3-5none, highRelevant to existing integrations; the model is deprecated.

Large 4 does not accept none, minimal, xhigh, or max. If you copied early Large 4 preview examples, replace none with low. Do not infer model support from values present in a shared SDK enum.

The Large 4 model card also marks the model as public preview. The Medium 3.5 card lists a deprecation date of 2026-10-31 and recommends Large 4 for new integrations.

Build multi-turn input and return function results

Preserve the complete item history, including reasoning and function calls. Answer text is useful for display, but it is not a complete conversation record.

Continue a conversation

Append every item from the previous output, then append the next user message. Add this after the first example:

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)

The second request contains the first user message, the complete first response, and the follow-up question. The helper also sends instructions again.

This is the documented replacement for previous_response_id. Keeping only a response ID cannot supply history to this stateless endpoint. Keeping only the printed answer discards other returned items.

Return a function result

Execute the function locally, then return its result with the matching call_id. Mistral’s function-calling example places type, name, description, and parameters in one tool object. The following example uses that structure with real local addition and a separate history.

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)

Check for Local result: 42, followed by an answer that uses that result. The model’s wording can vary.

The first request forces add; the second uses "none" to disable further calls, as defined in the API reference. This keeps the example to two generation steps and one local execution. For an open-ended agent loop, enforce your own round and execution limits because max_tool_calls is ignored.

Preserve all returned output before adding function results. Match results with call_id, not the output item’s id. If you permit multiple function calls, validate and return each result before requesting the next response.

Count the input before history grows

Count the complete next request, including history, instructions, and tool definitions. Counting only the newest user message misses content that your application will resend.

After the function example, use:

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)

This calls POST /v1/responses/input_tokens and prints input_tokens. It counts input without generating an answer. Use the same model, input, instructions, and tools when you later generate the response.

Compare that count with the selected model’s context window and leave room for output. Because truncation must remain "disabled", your application must decide when to reduce history.

Keep function calls with their corresponding results when managing history. Avoid removing arbitrary items from the middle of a tool exchange.

Token count is not a monetary estimate. Consult Mistral’s current API pricing when estimating repeated-turn costs and cache effects.

Diagnose migration failures

Check request configuration first, then inspect status and output items. Use the branch that matches the symptom.

  • The SDK rejects a keyword before sending a request. Check the installed SDK and its method signature. For the SDK used here, put store, background, and truncation inside additional_properties.
  • The API rejects the request. Reduce it to the first text example. Check the model ID, supported reasoning effort, and compatibility table. Restore optional fields one at a time after that request succeeds.
  • The model loses earlier context. Inspect the next input array. It must contain earlier messages and complete output items, not only a response ID.
  • The response has no answer text. Inspect status, error, and incomplete_details. Check whether it contains a function call awaiting execution. If generation reached its output budget, increase that budget or reduce reasoning effort within the model’s supported values.
  • The request reaches the wrong path. Check the final URL against https://api.mistral.ai/v1/responses. The Base URL and endpoint troubleshooting guide explains common path-construction mistakes.

For streaming, set stream=True and consume Responses events. The official Python streaming example reads each event through frame.data. Text arrives in response.output_text.delta; completion is signaled by response.completed.

Handle response.failed, response.incomplete, and error events too. A text delta alone does not establish successful completion. Background generation is disabled, so this setup does not need a polling loop.

Choose Responses, Chat Completions, or Conversations

Choose Responses when its item format fits your application and you want to control conversation history and function execution.

Your application needsStart withReason
Responses input/output items and Responses streaming eventsResponses APIIt preserves that format while your application manages state and functions.
An existing message-based integrationChat CompletionsYou can keep its message-oriented request and response handling.
Stored conversation continuation or Mistral-hosted toolsConversations APIIt provides conversation IDs and a separate hosted-tool interface.

Mistral’s Chat Completions guide describes its message-based format. The Conversations reference documents continuation through conversation_id.

For hosted search, Mistral documents web_search and web_search_premium under Conversations and Agents. That capability is separate from Responses’ client-executed function tools.

If your current application depends on stored continuation or hosted tools, evaluate Conversations before migrating its request payload. If your application already owns those responsibilities, validate the text request, follow-up turn, and function round trip above before connecting the full agent.

Ready to optimize your LLM workflow?

Join thousands of developers building faster, smarter, and more cost-effective AI applications with BetterToken.

Get Started for Free