> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inputapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Multi-turn conversations

> Carry message history into follow-up requests.

## Who keeps the history?

Chat Completions sees the `messages` sent with each request. Reusing an SDK client or API key does not automatically include earlier turns.

A plain text conversation sends the user question, assistant reply, and next user question in order. Isolate history by user and conversation. For concurrent requests in one conversation, use a stable history snapshot so replies do not scramble the order.

## A complete two-turn example

Follow the [Python SDK guide](/en/guides/python.md) to install dependencies and set the three environment variables. Select a model supporting ordinary Chat Completions text. Save as `conversation.py` and run `python conversation.py`. It sends two real requests; the second includes the first reply.

```python theme={null}
import os
from openai import OpenAI, APIConnectionError, APIStatusError

messages = []
with OpenAI(
    base_url=os.environ["API_BASE_URL"].rstrip("/"),
    api_key=os.environ["API_KEY"],
    timeout=60.0,
    max_retries=0,
) as client:
    try:
        for prompt in ["Suggest a short name for a coffee shop.", "Explain that name in one sentence."]:
            messages.append({"role": "user", "content": prompt})
            result = client.chat.completions.create(
                model=os.environ["API_MODEL"],
                messages=messages,
            )
            choice = result.choices[0] if result.choices else None
            if (choice is None or choice.finish_reason != "stop"
                    or choice.message.refusal or choice.message.tool_calls
                    or not choice.message.content):
                raise SystemExit("Conversation turn did not produce a complete text reply.")
            messages.append({"role": "assistant", "content": choice.message.content})
            print(choice.message.content)
    except APIStatusError as error:
        raise SystemExit(f"Request failed (HTTP {error.status_code}). Check the request logs.")
    except APIConnectionError:
        raise SystemExit("Connection failed. Check the API address and network.")
```

This example handles text only and stops on refusal, truncation, or tool calls. Tool conversations must retain the full assistant tool call and its matching results. Models requiring reasoning fields or other protocol extensions also need the relevant fields preserved; copying only `content` is insufficient. See [tool calling](/en/guides/tool-calling.md).

## Bound the context

Check the model's context limit and leave room for the current input and reply. Longer histories send more data per request. Retain recent complete turns and summarize older content when your application allows it. Summaries can lose details and cannot replace records that must remain exact.

Keep tool calls paired with their results when trimming history. Preserve necessary application instructions. If the context is too long, adjust the history before retrying; resending the same payload generally does not help.

## Responses state

Applications can send the necessary context explicitly in Responses `input`. Using `previous_response_id` instead depends on channel storage, ID visibility, and routing. Confirm these with your deployment administrator and avoid mixing response IDs from other services or channels.

Resupply instructions and tool definitions as required by the selected model and protocol. Linking a previous response is not a promise that all settings carry over. See the [Responses reference](/en/api-reference/responses.md).

## Python: explicit Responses history

Save as `responses-conversation.py`, configure the [Python SDK](/en/guides/python.md), and run `python responses-conversation.py`. Each turn resends instructions and the full history, without `previous_response_id` or relying on a stored previous response.

The example requires channel support for replaying Responses input items, `store: false`, and `include: ["reasoning.encrypted_content"]`. Models that need reasoning context must retain the relevant output items. If a channel cannot accept these fields or return required state, confirm a compatible approach rather than deleting reasoning items to bypass an error. `store: false` does not guarantee gateway or upstream log retention policies.

```python theme={null}
import os
from openai import OpenAI, APIConnectionError, APIStatusError

history = []
with OpenAI(base_url=os.environ["API_BASE_URL"].rstrip("/"),
            api_key=os.environ["API_KEY"], timeout=60.0, max_retries=0) as client:
    try:
        for prompt in ["Suggest a short name for a coffee shop.", "Explain that name in one sentence."]:
            history.append({"role": "user", "content": prompt})
            result = client.responses.create(
                model=os.environ["API_MODEL"], input=history,
                instructions="Answer briefly in plain text.",
                store=False, include=["reasoning.encrypted_content"],
            )
            if result.status != "completed" or not result.output_text.strip():
                raise ValueError("No complete text reply.")
            for item in result.output:
                if item.type == "reasoning":
                    continue
                if item.type != "message" or item.status != "completed":
                    raise ValueError("Unexpected or incomplete output item.")
                if any(part.type != "output_text" for part in item.content):
                    raise ValueError("Refusal or unsupported message content.")
            # Keep full output items, including encrypted reasoning and message metadata.
            history.extend(item.model_dump(exclude_none=True) for item in result.output)
            print(result.output_text)
    except APIStatusError as error:
        raise SystemExit(f"Request failed (HTTP {error.status_code}). No automatic retry.")
    except APIConnectionError:
        raise SystemExit("Connection failed. No automatic retry.")
    except (ValueError, TypeError, AttributeError):
        raise SystemExit("Conversation turn did not produce a complete text reply.")
```

Each turn validates completion, nonempty text, and refusals before appending the full `output` to history. Tests cover reasoning items, encrypted content, and message `phase`, not merely `output_text`. A failed turn stops the conversation and is never replayed. A complete first reply already printed remains visible.

Reference: [OpenAI conversation state](https://developers.openai.com/api/docs/guides/conversation-state).

[简体中文](/zh/guides/conversations.md)

[Prompt caching](/en/guides/prompt-caching.md) · [Reasoning models](/en/guides/reasoning-models.md) · [Context management](/en/guides/context-management.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.