Leviath

Structured context with structured flows makes structured agents.

Agents that do real work, in a small form factor: a model, a toolset and a context budget per stage, not per agent. One 74 MB Rust binary, nothing else to install.

10,000+agents in one process64 msfrom nothing to a running agent30 of 30jobs finished on data too big to fitHow these were measured ↓

Install

57 MB
curl -fsSL https://leviath.dev/install.sh | sh

What goes wrong

Long agent runs fall apart in the same five places.

Long runs forget what you told them

Fifty tool calls in, the one constraint you opened with has been squeezed out by file dumps and stack traces.

Context regions →

Grepping costs what planning costs

One model, one toolset and one prompt run the whole job, so the reasoning you pay a premium for is also the thing listing your files, and the only thing judging whether a fifth identical edit was progress.

Stages →

A crash mid-run means starting over, or doing it twice

The process dies with hours of tool calls inside it, and nothing left on disk can tell you which of them already wrote a file, ran a migration, or pushed a branch.

Run journal →

A handful of agents fills the machine

Every run brings its own process, its own memory, and its own copy of the runtime, so the box runs out long before the work does.

One shared world →

You can interrupt the agent, but not its sub-agents

Three levels down, a worker hits a question only you can answer and guesses instead, because the only conversation on offer is with the agent on top.

Live steering →

One file you write, and two things you never touch

The file is where you say what the agent does: its steps, which model each step gets, when it should hand you the keyboard, when it should stop and rethink, and how much it keeps in mind. The runtime reads that file as a graph, and it is the same graph you watch a real run move through in The Lair, or from your terminal with lev dash.

Leviath ships with 7 agents, so you never have to write one to start. The file below is one of them.

coder/agent.leviath
[stages.plan]                            ← Stagesmode = "interactive_points"              ← Live steeringmodel = { models = [{ provider = "anthropic", model = "claude-sonnet-5" }] }available_tools = ["read_file", "ask_user_choice", "edit_document"]max_iterations = 20[stages.implement]model = { models = [{ provider = "anthropic", model = "claude-opus-5" }] }available_tools = ["write_file", "edit_file", "bash"]max_iterations = 50[stages.implement.transitions.reassess]  ← Stagescondition = "stuck"stuck_after_iterations = 20stuck_after_minutes = 15stuck_after_same_file_edits = 5hint = "No forward progress - step back and reassess"[context.regions]                        ← Context regionstask         = { kind = "pinned",         budget = "2%" }plan         = { kind = "pinned",         budget = "5%" }conversation = { kind = "sliding_window", max_items = 40, budget = "20%" }

Real lines, trimmed for length.

becomes

lev run coder

agent-chosen when stuck automatic▤ parallel workers

All three are The Lair, which is part of this site rather than part of the binary: it runs in your browser and talks to the daemon on your own machine, so no run has to leave your computer to be watched.

The two you will not find in that file are the two nobody should have to set up: every agent lives inside one process, thousands at a time on one machine, and every step is written down as it happens, so a run that gets killed picks up instead of starting over.

Write your own →

Measured

What happens when the window runs out

Same binary, same tools, same permissions, same iteration budget. The only thing that differs is whether the context is one growing window or a pipeline of stages with a verifier at the end.

Runs that produced the report at all

Context window
Single-model loop, hardenedStructured agent
32k0 / 1010 / 1064k0 / 1010 / 10128k0 / 1010 / 10

One report of 17 exact figures, read out of a log corpus larger than the window, at three window sizes. The single-model loops here are the hardened ones: they are told in the prompt to wind down before the window fills and keep their results clean, which is every discipline the pipeline enforces, written as instructions. None of them returned a report. Neither did the ten plain single-loop runs at each size, left off so both bars share a scale. The failure is not a wrong answer but the model going quiet near a full window.

Invented figures in the delivered reports

Ten runs at 128k
Without verificationthe same six stages, minus one8 fabricatedWith verificationthe shipped recommendation0 fabricated

Both bars are the same pipeline on the same task at the same window; the second one has a verify stage that re-reads the corpus for every figure before the report ships. Without it, three of five reports came back complete, well formatted, and filled in from training priors: round-hour timestamps, canonical spellings the corpus deliberately avoids.

The caveats: our own tasks, built to stress a window rather than sample a normal day - read it as the edge, not a general score. Five runs of each, one round, pre-freeze. We built the structured agent and improved it twice while these ran: structural changes, not answers tuned to a task, and the one kind of job we never reworked is one we still lose. The single loop got no equivalent pass, because there is nowhere in one window to put one - the finding rather than a flaw in it. Both agents, the tasks and the runbooks are public: the benchmark harness. The full run tree publishes when the round freezes, whatever it says.

The honest map

Structure is survival gear, not a default

The question is not which agent is better. It is whether the work fits in one window, and Leviath is built to be either answer.

  • Use one loopIt all fits in the windowIf the material, the tools and the conversation fit with room to work, a single loop is the right shape. It is cheaper, it is faster, and in our own measurements it scores at least as well - sometimes better. Reach for nothing more.
  • Use structureThe material is bigger than the windowOnce the corpus cannot fit, the loop is not choosing what to keep - the window is, by age. Stages let you decide what survives each boundary, which is the difference between an agent that runs out of room and one that was given a plan for it.
  • Use structureA wrong answer is worse than noneWhen the deliverable has to be exactly right, put a stage between the draft and the reader whose only job is to check it against the source. A pipeline can require that. A prompt can only ask for it.

Both shapes are the same binary and the same blueprint file. A single loop is one stage with a big window; the pipeline is six with budgets between them. Choosing wrong is an edit, not a migration - which is why we can afford to tell you when not to use the complicated one.

Measured

Ten thousand agents, and the runtime out of the way

These came off one machine, an Apple M3 Max with 16 cores, running a mixed fleet of the bundled agents against a mocked model that answers in a flat 1.5 seconds, from one 74 MB binary.

Memory is live memory rather than RSS, which is the smaller of the two figures: what the process still holds once the pages the kernel can reclaim come out of it. CPU is a share of the whole machine, so 100% would be all sixteen cores.

The mocked model is the point: a real one would bury what the runtime costs under its own latency. So this is the floor the runtime adds rather than a forecast for your workload, and with a real model the first wall you meet is your rate limit rather than your machine.

Peak memory, by how many agents were running

Agents spawned
1034 MB100197 MB1,000945 MB10,0002.8 GB

Inference pool held at 512 for every tier, so the only thing changing is the number of agents. The runtime is paid for once, so the cost per agent falls as you add them: 3.4 MB each at ten, 0.28 MB each at ten thousand. That top tier is where the ladder stops rather than where the machine did: 2.8 GB of 128 GB, with CPU peaking at 44%.

Runs in flight at the same moment

Agents spawned
10131001361,0001,00210,0006,970

Same fixed pool of 512. Agents in this fleet start sub-agents, so more runs happen than were spawned; how many overlap at one instant is a separate number, and at ten thousand it comes out lower.

From cold, with nothing warm anywhere

Scenario
Daemon boot22 msNew run64 msPaused run resumed70 ms

Starting the daemon is measured inside each scenario rather than subtracted from it, so the 64 ms to begin a run already contains the 22 ms to boot one.

CPU while 1,000 agents were running

Inference pool width
1285.2%2565.9%5124.5%1,0243.4%

Averaged across the span where runs were actually active, so idle time at either end cannot flatter it: under 6% of sixteen cores at every pool width.

Time for 1,000 agents to finish, by inference pool width

Same fleet, same machine, one setting changed.
277spool 128
160spool 256
105spool 512
89spool 1,024

Agents spawned, inference pool held at 512

  • 10
  • 100
  • 1k
  • 10k

Memory over the whole run, and after it

Live memory

Seconds since the tier started

Every tier climbs while there is work and drops back to nothing when the last run drains. A leak would be the line that never comes back.

CPU over the same runs

Share of the machine

Seconds since the tier started

Ten thousand agents hold the machine at roughly 40% of sixteen cores for eleven minutes, and the smaller tiers barely mark the axis at all. Most of what is left is time spent waiting on a model.

Inference pool width, 1,000 agents spawned

  • 128
  • 256
  • 512
  • 1,024

A wider pool puts more of the work in flight

Live memory

Seconds since the tier started

The same thousand agents, four pool widths. A wider pool runs more of them at once, so the memory is higher while it lasts and it lasts a lot less time: 128 stays under 400 MB across five minutes, 1,024 peaks past 1.2 GB and is finished in ninety seconds.

CPU across the sweep

Share of the machine

Seconds since the tier started

Note the axis: this one tops out at 20% of the machine, not 100%. Read the area rather than the height: the total CPU spent falls at every step, from 14.5 machine-seconds at 128 to 2.9 at 1,024 for the same thousand agents, mostly because the wider pool is finished sooner.

All three repetitions are drawn in every chart, not an average of them, which is why each colour is three lines almost on top of each other. The bars above report the median of the three, so the tallest line here runs slightly above its bar.

For scale

The closest thing to a comparison

We do not benchmark other frameworks. Whatever baseline we wrote, somebody could fairly say we wrote it to lose, so here is a benchmark someone else ran. It measures a different thing to ours, and both sets of numbers have gaps worth knowing about before you put them side by side.

Somebody else measured these, on a workload that is not ours, with a memory metric that is not ours either. What that leaves is context, not a scoreboard.

One benchmark, published February 2026. These frameworks change fast enough that figures this old are somewhere to start your own measurement, not a fact about today. Benchmarking AI agent frameworks, n1n.ai, February 2026
FrameworkLanguagePeak RSSCPUCold start
AutoAgentsRust1,046 MB29.2%4 ms
RigRust1,019 MB24.3%4 ms
LangChainPython5,706 MB64.0%62 ms
PydanticAIPython4,875 MB53.9%56 ms
LlamaIndexPython4,860 MB59.7%54 ms
GraphBitJS/TS4,718 MB44.6%138 ms
LangGraphPython5,570 MB39.7%63 ms
  • Different workloads. Theirs sends 50 requests, 10 at a time; the ladder here spawns up to 10,000 agents. Neither answer substitutes for the other.
  • Theirs calls GPT-5.1 over the network, so a good share of what it times is the model. We mock the model at a fixed latency, which isolates the runtime but also means we publish nothing about real end-to-end speed.
  • The memory columns are close relatives rather than the same measurement. Theirs is peak RSS; ours takes out the pages the kernel can reclaim, which makes it the smaller figure. Subtracting one from the other would not mean much.
  • Cold start is the thinnest column on either side. The article reports that these frameworks "initialize" in that time without defining what it covers, and two of them land on the same 4 ms, so there is not much to compare against. Ours measures more (a separate daemon starting and answering a socket) and is correspondingly slower, which is a difference in scope rather than a result.
  • Reproducibility cuts both ways. Theirs does not name its cloud instances or how many times it ran, so a rerun would be hard to line up. Ours names the machine and the binary and publishes every repetition, on exactly one machine.

The Claude Agent SDK and Codex are not here because we could not find published figures for them on this axis. What circulates traces back to posts with no method attached, and a gap seemed better than a citation like that. If you measure them yourself you will have better numbers than anyone currently quoting them, ours included.

7 agents out of the box

Every one is a file like the one above, already written. Pick one to see its shape.

coder

Full coding workflow with an approved plan, an optional spike, and stuck detection.

agent-chosen when stuck automatic▤ parallel workers

checks in on the plan, or proceeds unattendedspikes the risky part before writing itmeasured stuck detection
lev run coder --task "add rate limiting to the API"

Explore the full catalog →

Also in the box: a terminal dashboard (lev dash) · sub-agents and fan-out · sandboxing and taint tracking · MCP tool servers · REST + WebSocket API · OpenTelemetry tracing

Who builds this

Leviath is written by Gerald McAlister, and it is MIT licensed. One person, in the open, with the changelog as the record of it.

Bugs, security reports and questions all go to the issue tracker, which is the only place any of them gets answered in public. Open an issue