Conversation state
On Chat Completions and Messages every request carries its full history: keep the message list client-side, append to it each turn, and send it. Responses is the exception: turns are stored by default and chain by previous_response_id, so a client can send only its new input.
Works with
Every model. Server-side state is a property of the Responses API, not of any model: store and previous_response_id work on sonnet, kimi, and gpt alike.
Request
- Chat Completions
- Responses
- Messages
- Chat Completions
- Responses
- Messages
messages = [{"role": "user", "content": "My name is Quill."}]
first = client.chat.completions.create(model="mindshub_air", messages=messages)
messages.append(first.choices[0].message)
messages.append({"role": "user", "content": "What's my name?"})
second = client.chat.completions.create(model="mindshub_air", messages=messages)
print(second.choices[0].message.content)
first = client.responses.create(model="mindshub_air", input="My name is Quill.")
second = client.responses.create(
model="mindshub_air",
input="What's my name?",
previous_response_id=first.id,
)
print(second.output_text)
messages = [{"role": "user", "content": "My name is Quill."}]
first = client.messages.create(model="mindshub_air", max_tokens=256, messages=messages)
messages.append({"role": "assistant", "content": first.content})
messages.append({"role": "user", "content": "What's my name?"})
second = client.messages.create(model="mindshub_air", max_tokens=256, messages=messages)
print(second.content[0].text)
const messages: any[] = [{ role: "user", content: "My name is Quill." }];
const first = await client.chat.completions.create({ model: "mindshub_air", messages });
messages.push(first.choices[0].message, { role: "user", content: "What's my name?" });
const second = await client.chat.completions.create({ model: "mindshub_air", messages });
console.log(second.choices[0].message.content);
const first = await client.responses.create({ model: "mindshub_air", input: "My name is Quill." });
const second = await client.responses.create({
model: "mindshub_air",
input: "What's my name?",
previous_response_id: first.id,
});
console.log(second.output_text);
const messages: any[] = [{ role: "user", content: "My name is Quill." }];
const first = await client.messages.create({ model: "mindshub_air", max_tokens: 256, messages });
messages.push({ role: "assistant", content: first.content }, { role: "user", content: "What's my name?" });
const second = await client.messages.create({ model: "mindshub_air", max_tokens: 256, messages });
console.log(second.content[0]);
Resending the full conversation in input every turn also remains valid on Responses, and is what the OpenAI SDK does when you aren't chaining. Prompt caching keeps that cheap: repeated prefixes bill at roughly a tenth of the input rate.
Server-side state on Responses
Responses are stored by default (store: true, as on OpenAI). Send store: false to keep a turn out of storage entirely; its id is then not retrievable and cannot be chained from.
Stored turns are readable and removable:
| Call | Behavior |
|---|---|
client.responses.retrieve(id) | The response as it was returned, output items included. |
client.responses.input_items.list(id) | That turn's own input items, not the inherited history. |
client.responses.delete(id) | Hard delete. The content is gone, not flagged. |
client.responses.cancel(id) | Accepted only for background: true requests; every request completes synchronously, so there is nothing to cancel and the call returns 400 otherwise. |
Boundaries worth knowing:
- Stored turns expire after 30 days. After that the id is a
404and chains through it shorten. - A chain is walked at most 25 turns back. Beyond that, and when an older turn has expired or been deleted, the request is still served with the history that remains and the response carries
X-MindsHub-Chain-Truncated. - An unknown
previous_response_idis a404(previous_response_not_found), not a silently context-free answer. instructionsare per turn and deliberately not carried acrossprevious_response_id, matching OpenAI. Send them again on each request if you want them to persist.- The
conversationparameter (OpenAI's Conversations API) is rejected with a400, as arepromptandcontext_management. A client that believes we are holding its thread would otherwise stop sending history and lose context on every turn.
Response
On Responses the id on every response is what you chain from. Nothing else about the response shape changes on any API.
Per-model differences
None. State is handled before the request reaches a provider.
Errors you can hit
404 previous_response_not_found for an unknown, expired, or deleted id; 400 unsupported_parameter for conversation, prompt, or context_management; 400 from cancel on a non-background response. See Errors.