Execution model and durability
maiden runs a manual agent loop — it does not delegate to a provider’s built-in agent. That is a deliberate choice: owning the loop is what lets maiden decide exactly where to checkpoint and which tools are available on each turn.
The loop
Section titled “The loop”Handling one user message on a thread works like this:
- Load the thread’s durable history from the store. If there is any, this run is a resume.
- Append the user message.
- Loop:
- Ask the
Providerfor the next turn, given the system prompt, the history so far, and the available tool specs. - If the model returned tool calls, dispatch each through the registry, collect the results, append them to the history, and checkpoint.
- If the model returned a final answer, append it, checkpoint, and return.
- Ask the
- Guard: if the loop reaches
max_turns(fromagent.toml) without a final answer, it checkpoints and aborts with an error.
Tool failures do not crash the loop. A trap, a timeout, or an error from a tool
is fed back to the model as that tool’s output (a small JSON error object), so
the model can recover or explain — the run continues.
Checkpoints
Section titled “Checkpoints”The unit of durability is the thread’s full conversation: an ordered list of entries (user messages, assistant turns with their tool calls, and tool results). maiden serializes that list and writes it after every round — after each batch of tool results, and after the final answer.
Writes are crash-safe. The filesystem store writes to a temporary file and then atomically renames it into place, so a reader concurrent with a writer always sees either the old snapshot or the new one — never a half-written file.
Durable resume
Section titled “Durable resume”Because the whole conversation is on disk after each turn, you can kill the process at any point and start it again, and a request on the same thread picks up where it left off. There is no replay and no event log to fold — resume is just “load the last snapshot and keep going.”
This is a snapshot/resume model, not an at-least-once replay model. A run that was interrupted mid-turn (after tool side effects but before the checkpoint) is re-driven from the last checkpoint; design tools to tolerate being called again.
One loop at a time
Section titled “One loop at a time”The HTTP server, schedules, and channels all share a single runtime behind one lock, so only one agent loop runs at a time. This keeps thread state trivially consistent — there is no concurrent mutation of a thread to reason about. It also means a long-running stream holds the runtime for its duration; maiden is built for durable, sequential agent work, not high-concurrency request serving.
Threads
Section titled “Threads”A thread is a named, independent conversation. Different thread ids have separate histories and never interfere. Thread ids are sanitized to a safe filename before hitting disk, so any string is a valid thread id.