# Multi-turn conversations

The model is stateless: each request must carry the full conversation history. Append every assistant message back into `messages` exactly as returned, then append the next user turn. This applies uniformly to plain replies, tool calls, and streamed responses. Parameters are documented on the [Chat completions API](https://docs.ifm.ai/docs/chat-completions.md) page.

## Continue a conversation

Reasoning models return `reasoning_content` alongside `content`. Replay it verbatim — an empty string `""` is a valid value, so keep it rather than dropping the field or sending `null`.

```
msg = resp.choices[0].message

messages.append({
    "role": "assistant",
    "content": msg.content,
    "reasoning_content": msg.reasoning_content,   # keep "" as-is
})
messages.append({"role": "user", "content": "Now double it."})

resp = client.chat.completions.create(model=os.environ["IFM_MODEL"], messages=messages)
```

| Field | Meaning |
| --- | --- |
| reasoning_content | The canonical field, matching vLLM and SGLang. Use this one. |
| reasoning | Mirror with the same value, kept for older clients. Send either; sending both is harmless. |

## Tool turns and streaming

The same replay rule covers both. Tool turns interleave in the one `messages` array — see [Custom function calling](https://docs.ifm.ai/docs/custom-function-calling.md). Streamed turns are assembled from deltas before being appended — see [Streaming](https://docs.ifm.ai/docs/streaming.md). To keep a long conversation on the compute node that already holds its prefix, see [Session routing](https://docs.ifm.ai/docs/session-routing.md).

_Last updated: September 2, 2026_
