How maiden fits together
maiden is a small system built from narrow modules behind small seams. This page explains the shape — what each part does and how they connect — so the rest of the docs have somewhere to point.
The one idea: everything is a Tool
Section titled “The one idea: everything is a Tool”The model can invoke three very different things: a sandboxed WASM function, a
tool exposed by an MCP server, and a whole subagent. maiden collapses all three
into a single trait — Tool — and puts them in one registry with one dispatch
path.
A Tool is just:
- a name,
- a spec (description + JSON input schema) shown to the model, and
- a call that takes a JSON argument string and returns a JSON result string.
Because a subagent and an MCP tool both satisfy that interface, the agent loop never needs to know which kind it is calling. This is the single decision that keeps maiden’s concept count low.
The modules
Section titled “The modules”| Module | Responsibility |
|---|---|
discover | Folder → AgentDef (model, instructions, skills, tool policy). |
load | Recursive assembler: folder → runnable Runtime (binds tools, loads subagents, connects MCP servers). |
sandbox | The wasmtime tool host — resource limits, capability gating, a compiled-component cache with hot reload. |
tool | The Tool trait and the dynamic Registry. |
provider | The Provider seam over a model backend (OpenAI, Anthropic, and a mock). |
runtime | The agent loop: complete → dispatch tools → checkpoint → resume. |
state | The StateStore seam and its atomic filesystem implementation. |
serve | The HTTP front door. |
trigger | Schedules and channels that start runs off the clock or inbound events. |
The seams
Section titled “The seams”Three boundaries are drawn as traits so the internals can change — and so tests can substitute fakes:
Providerwraps the model backend. The runtime only ever hands it the system prompt, the conversation, and the tool specs, and gets back a “next turn.” OpenAI, Anthropic, and the offline mock all sit behind it. See Choose a provider.Toolwraps anything the model can call, as described above.StateStorewraps durable thread storage. The filesystem store ships; anything byte-oriented (SQLite, Postgres) can replace it without touching the runtime.
Third-party libraries — the model client and the WASM engine — live entirely
behind provider and sandbox. Nothing else in the codebase depends on them,
which is what lets maiden stay a single small binary.
How a request flows
Section titled “How a request flows”loadturns the folder into aRuntime: anAgentDef, aProvider, aRegistryofTools, and aStateStore.- A request (via
run,serve, or a trigger) calls the runtime with a thread id and a message. - The agent loop drives the provider and the registry, checkpointing after every turn.
- The final answer is returned; the thread’s history is on disk.
To see the loop itself, read the execution model. To understand the trust boundary around tools, read the security model.