James looked at his tutorclaw-mcp project from Module 9.2. One tool: register_learner. It worked. He had tested it, connected it to OpenClaw, verified it from WhatsApp. But something nagged him.
He restarted the server. Then he sent a message from WhatsApp: "Show me my learning progress."
Nothing. The learner he had registered was gone.
"That is the problem with in-memory storage," Emma said, looking at his screen. "Every restart wipes the slate. Your learner registered five minutes ago and the server has already forgotten them."
"So I need a database."
"You need files on disk. JSON files. Simple, local, no database server to install." She pointed at the spec they had designed in Module 9.3, Chapter 2. "Three state tools: register_learner upgraded to persist data, get_learner_state to read it back, update_progress to change it. Describe each one to Claude Code. One tool per prompt. You have the specs from yesterday."
You are doing exactly what James is doing. Three tools, JSON persistence, data that survives restarts.
Open Claude Code in your tutorclaw-mcp project. Send this prompt:
Review the spec Claude Code produces. Check the same elements you checked in Module 9.2:
Element
What to Look For
Tool description
Specific enough that an agent knows when to call this instead of get_learner_state or update_progress
Input parameters
Name (required), anything else optional
Output format
Returns the learner record including the generated ID
Persistence
Reads from and writes to data/learners.json
If the tool description is vague, steer it. The agent will have nine tools eventually. A description like "handles learner data" is useless when three different tools all handle learner data. A description like "Register a new learner by name. Call this when a user wants to sign up or create a new learning profile for the first time" gives the agent a clear selection signal.
Once the spec looks right:
Claude Code creates the data/ directory, sets up the JSON file handling, and updates your server with the persistent version of register_learner. Run the tests:
If tests fail, paste the output back to Claude Code and ask it to fix them. That is the cycle.
Now add the second tool. Send this prompt to Claude Code:
Review the spec. Pay special attention to the tool description. This tool reads state. It does not change state. The description must make that distinction clear, because the agent will also have update_progress, which does change state. If the descriptions overlap, the agent will pick the wrong one.
Good distinction:
If Claude Code's description does not make the read-versus-write distinction, steer it:
Approve the spec, let Claude Code build, run tests:
The third state tool. Send this prompt:
Review the spec. This tool writes state. The description should say so. The output should return the updated state so the agent can confirm what changed.
Approve, build, test:
This is the verification that matters most. Everything before this was unit testing: does each tool work in isolation? The restart test answers a bigger question: does your data survive?
Call register_learner through Claude Code or your test suite. Confirm you get a learner record back with an ID.
Kill the running server process. The in-memory version from Module 9.2 would lose everything here. Your JSON version should not.
Query the learner you registered before the restart. If the data comes back with the correct name, tier, and default state values, the persistence layer works.
If the data is missing, something went wrong with the JSON file write. Ask Claude Code:
This is the normal cycle: test, find the gap, describe the fix, verify again.
Do not wait until all 9 tools are built to connect. Connect now with three tools.
Start the server, then connect to OpenClaw the same way you did in Module 9.2:
Open the dashboard. Navigate to Agents > Tools. You should see three tools: register_learner, get_learner_state, update_progress.
Now pick up your phone. Send a WhatsApp message:
The agent calls register_learner and returns a learner ID. Then send:
The agent calls get_learner_state and returns chapter 1, predict stage, 0.5 confidence.
Three tools, working from your phone. As you add more tools in the next three chapters, they appear automatically when you restart the server. You do not need to reconnect; openclaw gateway restart picks up new tools from the running server.
Three tools now handle the state layer of TutorClaw:
All three use JSON files on disk. No database server. No cloud storage. The data survives restarts because it lives in files, not in memory.
The mock auth pattern (MOCK_LEARNER_ID and MOCK_API_KEY) lets you test without building a real authentication system. Every tool call uses the same hardcoded learner. Real auth with unique API keys comes later in the chapter. This is a common development technique: mock the parts you are not building yet so you can focus on the parts you are.
Ask Claude Code to review all three state tool descriptions together:
What you are learning: When multiple tools operate on the same data (learner state), the descriptions must carve out distinct responsibilities. Overlap in descriptions means confusion in tool selection.
What happens if you call get_learner_state for a learner that does not exist?
What you are learning: Tools need to fail clearly. An agent that gets a vague error cannot recover. An agent that gets "Learner not found. Register this learner first using register_learner" knows exactly what to do.
Ask Claude Code to think about the tradeoffs of JSON file storage:
What you are learning: JSON files work for a single-user local product. They break under concurrent writes, large datasets, or multi-server deployments. Knowing the limits of your storage choice is a product design skill, not just a technical one.
James registered a learner, stopped the server, started it again, and called get_learner_state. The data was there. Name, tier, default chapter, default stage. All of it.
"JSON files on disk," he said. "That is all it took."
"For now," Emma said. She paused, then added: "Honestly, I am not sure exactly when JSON files stop being enough. I have seen projects run on flat files longer than anyone expected, and I have seen them break earlier than planned. It depends on how many learners hit the server at once, how often you write, how big the files get." She shrugged. "The right answer is: ship the product first. Scale the storage later. You will know when JSON is not enough because the tests will start failing under load."
"So we have three tools. State is handled."
"State is handled. But your tutor has nothing to teach yet." She opened the spec from Module 9.3, Chapter 2. "Content tools are next. Chapter text, exercises, teaching material. The tutor needs a curriculum before it can tutor."