# Models and formats

> Chat Completions and Responses, which models work, where our messages go in the request, and what the size ceiling assumes.

## Two formats

Every call names the OpenAI API it is for. The SDKs do this for you: `memory.chat` is Chat Completions and `memory.responses` is Responses.

| Format | SDK surface | History field | Tool results |
|---|---|---|---|
| `chat.completions` | `memory.chat` | `messages` | `tool` messages |
| `responses` | `memory.responses` | `input` items | `function_call_output` items |

A memory keeps each message in the format it arrived in, and messages come back exactly as stored when the request is in the same format. A memory can switch format mid-conversation: messages from the other format are converted to their text, tool calls and tool outputs, and anything else (images, reasoning items) is left out of the converted copy.

Messages and items are stored as you send them: content parts, images, tool calls, tool outputs and reasoning items included. Whatever you put in `requestFields` (`model`, `tools`, `tool_choice`, `temperature`, `reasoning`, `instructions` and the rest) passes through unchanged, except `previous_response_id` and `store`, which are dropped because we hold the history.

## What we add to the request

Our own text reaches the model as instruction messages, in the role your instructions use:

- Chat Completions: `system` messages, or `developer` messages when your instructions are `developer` messages.
- Responses: `developer` message items.

There are three kinds:

- **The facts block**, right after your instructions: facts remembered from history that has left the view.
- **The recall block**, just before the user message it was recalled for, between `[recalled_memories]` and `[/recalled_memories]`: possible memories from earlier in the conversation, dated, to be used only when relevant.
- **The note ask**, last, only on calls where history is leaving the view.

None of them names a tool. The model knows the note tool by its description. See [How it works](https://threadlessai.com/how-it-works#what-the-model-sees) for an example of each.

## Models

Any model that the API you use accepts works. The request you get back is the request you would have sent, with the history managed; we don't call the model.

The note ask relies on the model calling a tool when asked, so use a model that supports function calling. The note is how facts get written, and history leaves the view only once its facts are written.

## The size ceiling

The ceiling the history is kept under is ours and constant: we assume a 200k-token context window and keep room for the reply. A model with a smaller window is not refused; whether to use one is your call. Sizes are measured with our own estimate and corrected by the token count your provider reported on the previous call, which is why `report` should carry the response's `usage`.

## Streaming

`report` takes the complete response. If you stream, report the final response once the stream ends: for Responses, the `response` of the `response.completed` event; for Chat Completions, a completion object assembled from the stream, with `usage` when you request it (`stream_options: { include_usage: true }`).
