Chat log format

DataMind Oda keeps each chat's lasting record as a session log file on your computer. This page covers the format of that log: its header, the events inside it, and the rules Oda follows when reading and writing it. It is written for people who inspect, support or process chat logs. Where the files live and how Oda keeps them is covered in Chat logs on disk.

What a chat log holds

A log holds everything the model saw in the chat, in the order it happened:

The first line is the header. It names the chat and how it started, and Oda can read it on its own to decide how to treat the file before reading anything else. The header carries:

The number of inherited events is kept with the log, not among the records a reader replays.

Before trusting a header, Oda checks its fields:

A log written by a different version of Oda is converted or refused when it opens; see Opening older chats.

Messages, roles and content

Every message carries a role:

RoleWhat it carries
usermessages from you and other human input
modelOda's answers, including the reasoning that came with them
toola tool result, as a message of its own
developernotes about which tools the model had

Message content comes in a few kinds: text, reasoning, image, file, tool-call and tool-result. Images are held as attachments in PNG, JPEG, WebP or GIF; each image record carries its media type, its size and its dimensions.

Two details matter when you process a log:

What a log refuses to store

Oda stores each value in a log exactly as it was, and refuses a value it cannot store that way instead of storing an approximation. This covers:

The same test runs on the chat's metadata, refused with session metadata must be losslessly JSON-serializable. When a value is refused, nothing from that batch is stored. For the messages a failed check can show, see Chat log problems.

Reading part of a log

A log is read in pieces, not all at once. Saved events keep their order and their sequence numbers, and reading a log never changes it. A read asks for two things:

  1. a starting position: the sequence number of the first event to return;
  2. a length: how many events to return.

Both are whole numbers of zero or more; anything else is refused with read offset must be a non-negative safe integer, got <v> or read length must be a non-negative safe integer, got <v>, depending on which value is wrong. By default a read starts at the beginning and returns the rest of the log. A read that starts at or past the end returns nothing; it is not an error.

A later read never shows an older state than an earlier one.

Read models and checkpoints

Oda also keeps small current values built from a chat's log, so it can present the chat's state without replaying every event. These values are called read models.

Questions, answered

What does a chat log contain?

Everything the model saw in the chat: the messages, the tool calls and their results, the files and images, and the settings each request ran with, all in order. The header at the top names the chat and how it started.

What do the roles in a log mean?

Each message carries one of four roles: user, model, tool or developer. They say where the message came from; the table above lists what each role carries.

Which image types can a log hold?

PNG, JPEG, WebP and GIF. An image is stored with its media type, its size and its dimensions, and a reference to the attachment that holds it.

Why is a tool result a message of its own?

So a reader sees every result exactly where it belongs in the conversation. The result message keeps the id of the call it answers and is marked when the call failed. Logs from older formats are converted as they open, and their results also become messages of their own.

What values does a log refuse to store?

Values that JSON cannot keep exactly: negative zero, infinity and NaN, undefined members, empty array slots, hidden or symbol-named members, cycles, and instances of custom classes. Oda refuses them rather than storing a changed value.

How do I read only part of a log?

Ask for a starting position and a length. The position is the sequence number of the first event to return, and the length is how many events to return. By default a read returns the log from its start, and a position at or past the end returns nothing.

What does the position in a read-model snapshot mean?

It is the sequence number of the last event that the snapshot's values account for, so you can tell how current they are. A chat with no events yet reports the position -1.

Do saved read-model values go stale?

They can lag behind the chat, but they are never wrong: when a saved checkpoint no longer fits the log, Oda rebuilds the state from the log instead of serving it.