Knaph

A Conversation7 of 37

Check the History

In [Keeping the History](keeping-the-history) the messages list was the whole memory of the conversation, and mini adds to it on every turn. A bug in that code (a reply added twice, a tool result that went missing) doesn't crash anything straight away. It turns up later as a confusing error from the API, or a model that seems to have lost the thread. A small check, run before each request, catches it where it happens. Write check_history(messages). It gets the list as the API would get it: each message a dict with a role and a content, where the content is either a string or a list of blocks. Blocks have a type: "text", "thinking", "tool_use" (with an id) or "tool_result" (with a tool_use_id). You met the first two in [Reading the Reply](reading-the-reply); the module after this one is about the other two. For now, all you need to know is that when the model asks for a tool, the next user message must carry one result for each call, with the same id. Go through the messages in order, and return the first problem you find: 1. Unknown role. A role other than "user" or "assistant": problem at I: unknown role R, where I is the message's position (from 0) and R its role. (The system prompt is not a message; it has its own parameter.) 2. The first message must be from the user: problem at 0: the first message must be from the user. 3. Roles alternate. A message with the same role as the one before: problem at I: two R messages in a row. 4. In a user message, every tool result must answer a call made in the assistant message just before it: problem at I: result for unknown tool call ID. Check the results in the order they appear. 5. In the same user message, every call from the message before must have its result: problem at I: no result for tool call ID, checking the calls in order. After the loop, the history must end with a user message, since that is what the model answers: problem at I: the last message must be from the user, where I is the last position. If nothing is wrong, return OK. For example, this history (a reply added twice by mistake): ``json [ {"role": "user", "content": "Hi!"}, {"role": "assistant", "content": "Hello!"}, {"role": "assistant", "content": "Hello!"}, {"role": "user", "content": "Bye"} ] ` gives problem at 2: two assistant messages in a row. <details> <summary>A hint</summary> Keep a list of the tool call ids in the previous assistant message (empty after a user message). In a user message, compare the tool_use_ids of its tool_result blocks with that list, in both directions. The blocks()` helper turns a plain-string content into a list, so you never need to check for strings yourself. </details>

Sign in to try this exercise.