Navan went looking for the state file and couldn't find it.
Every tool he had ever used kept state somewhere. Docker had its volumes and layers in /var/lib/docker. Git had its .git directory with its object store and refs and packed files. Terraform had terraform.tfstate, a JSON file that was simultaneously the most important file in your infrastructure and the most dangerous file to edit by hand.
Agate had .ai/. He opened the directory and looked inside.
interview.md. The questions and answers from the interview phase. design/overview.md. design/decisions.md. sprints/sprint-01/plan.md. sprints/sprint-01/assessment.md. Markdown files, all of them. Human-readable. Human-editable. No binary blobs. No serialized objects. No state.json.
"Where's the state?" Navan asked Jay, who was sitting at the next desk writing suggestions into a running Agate session.
"You're looking at it."
"These are just... files. Markdown files."
"That's the state. The existence of a file is the state. If interview.md exists, the interview phase is complete. If sprints/sprint-01/plan.md exists, sprint one has been planned. If sprints/sprint-01/assessment.md exists, sprint one has been assessed. The state is inferred from what files exist and what checkboxes are checked."
Navan opened the sprint plan. The tasks were markdown checkboxes: - [x] Implement CSV parser, - [x] Implement JSON formatter, - [ ] Generate integration tests. The checked items were complete. The unchecked items were pending. The state of the sprint was literally visible in the document.
"There's no state.json," Navan said, more to himself than to Jay. "No database. No serialization layer. The filesystem is the database. The directory structure is the schema. The markdown checkboxes are the records."
"And you can read it all with your eyes," Jay said. "Try that with terraform.tfstate."
Navan wrote a note in his physical notebook: .ai/ directory = all Agate state. No state.json. State = file existence + checkbox status. Everything human-readable. He underlined "human-readable" twice.
The elegance of it settled in slowly. No migration scripts. No schema versioning. No deserialization bugs. If you wanted to know what Agate had done, you opened the .ai/ directory and read. If you wanted to change what Agate would do next, you edited a markdown file. The state was not abstract. It was not hidden behind an API. It was text on disk, organized in directories, readable by any human with a text editor.
Later, Navan showed the .ai/ directory to a friend who was working on a different AI coding tool. The friend's tool used a SQLite database to track agent state, with migrations, with an ORM, with all the scaffolding that databases demanded.
"Markdown checkboxes," the friend repeated, incredulous.
"Markdown checkboxes," Navan confirmed.
His friend stared at the directory listing for a long time. Then he said, very quietly, "I think we overengineered something."
"I think we overengineered something." Every software engineer has had this realization at least once. The lucky ones have it early.