In the previous chapter, Task Structure & States, we learned what a valid task looks like. We discussed the specific grammar of "status," "content," and "activeForm."
But knowing how to write a task is only half the battle. If you write a perfect to-do list on a napkin and then throw it away, itβs useless. You need a way to keep that list safe while you work.
In this chapter, we will explore State Persistence: the mechanism TodoWriteTool uses to remember the list across the entire conversation.
Imagine you are in a long strategy meeting.
Without persistence, every time the AI Agent performs an action (like reading a file or running code), it would suffer from amnesia and forget what it was trying to achieve.
The Solution: The TodoWriteTool acts as that permanent whiteboard. It saves the list into the application's global memory (called appState), ensuring the plan survives throughout the session.
Let's look at a concrete scenario.
FileWriteTool) to actually write the code.completed.For step 3 to happen, the list defined in step 1 must be saved securely.
Before looking at the code, let's visualize how the tool saves data when called.
The tool is smart. It knows who is talking.
sessionId.agentId.This prevents a helper agent from accidentally erasing the main boss's to-do list!
Let's look at TodoWriteTool.ts to see how this is implemented. We will break it down into tiny pieces.
First, the tool needs to decide where to store the list. It checks the context.
// Inside TodoWriteTool.ts -> call()
// If an agentId exists, use it. Otherwise, use the general session ID.
const todoKey = context.agentId ?? getSessionId()
// Retrieve the entire current memory of the app
const appState = context.getAppState()
Explanation: todoKey is the unique label for our whiteboard. context is provided by the system automatically when the tool runs.
There is a special rule: If every task on the list is completed, the tool assumes we are starting fresh next time.
// Check if every single item is marked 'completed'
const allDone = todos.every(item => item.status === 'completed')
// If all done, reset to an empty list [].
// Otherwise, keep the current tasks.
const newTodos = allDone ? [] : todos
Explanation: This auto-cleanup keeps the memory from getting clogged with old, finished tasks. If the project is done, the whiteboard is wiped clean.
This is the most important part. We use setAppState to permanently write the data.
context.setAppState(prev => ({
...prev, // Keep everything else in memory (chat history, etc) unchanged
todos: {
...prev.todos, // Keep lists belonging to other agents unchanged
[todoKey]: newTodos, // UPDATE only our specific list
},
}))
Explanation:
prev (previous) state.todos section.[todoKey]) and overwrite it with newTodos.Finally, we tell the Agent what happened.
return {
data: {
oldTodos, // What it looked like before
newTodos: todos, // What we just saved
},
}
Explanation: The tool returns both the old and new lists. This confirms to the Agent that the save operation was successful.
In this chapter, we learned:
agentId or sessionId to ensure we don't overwrite someone else's list.Now that we understand the data structure (Chapter 1) and how to save it (Chapter 2), we are ready to combine everything into the formal definition of the tool.
Generated by Code IQ