Recursive AI

Results

All onellm docs

What OneLLM measured about itself for the 1.0 release, and how. Every number below is OneLLM's own.

Run date: 2026-11-06. Commit: the 1.0.0 tag. Machine for the speed rows: AMD Ryzen 9 7950X3D, 16 physical and 32 logical cores, 125 GB, Linux Mint 22.3 (kernel 7.0.0-38), .NET SDK 10.0.403, runtime 10.0.14, BenchmarkDotNet 0.15.8, on an otherwise idle machine (1-minute load average between 1.1 and 8.4 during the runs).

Speed

Method: BenchmarkDotNet suites in bench/ against a local mock server that replays deterministic provider responses over loopback, so the numbers are client code and not a network or a vendor. The workloads, the exact settings and the way the gate runner records the machine and its load are in bench/README.md. Each row is the mean of the measured iterations; allocations are bytes per operation from the memory diagnoser.

A request row is a whole non-streamed turn: build the request from a history of the stated size, serialize it, send it over loopback and parse a one-line answer. A stream row reads a 2,000-event text stream (divide by 2,000 for the per-event cost); a first-event row stops at the first text event of a 50-event stream.

RowParametersMeanAllocatedPeak working set (MB)
request-anthropic1k tokens50.0 us31.7 KB146
request-anthropic50k tokens1.022 ms714.1 KB91
request-anthropic200k tokens5.788 ms2.75 MB106
request-gemini1k tokens37.0 us27.1 KB141
request-gemini50k tokens779.1 us839.0 KB88
request-gemini200k tokens1.835 ms3.27 MB100
request-openai-chat1k tokens35.9 us15.1 KB164
request-openai-chat50k tokens652.9 us291.2 KB89
request-openai-chat200k tokens1.301 ms1.11 MB91
request-openai-responses1k tokens38.1 us21.5 KB163
request-openai-responses50k tokens692.5 us297.7 KB86
request-openai-responses200k tokens1.422 ms1.12 MB91
stream-anthropic2,000 events610.7 us33.7 KB105
stream-gemini2,000 events699.5 us155.5 KB131
stream-openai-chat2,000 events813.7 us639.7 KB140
stream-openai-responses2,000 events621.0 us96.3 KB116
first-event-anthropicfirst text event54.8 us31.9 KB144
first-event-geminifirst text event43.4 us29.4 KB143
first-event-openai-chatfirst text event45.7 us13.8 KB163
first-event-openai-responsesfirst text event52.6 us22.2 KB147

The agent loop

One run is eleven model turns (ten tool-calling turns and a final one) on the scripted provider, with the default runtime, an in-memory store and no record sinks: 78.2 us and 56.8 KB per run, 7.1 us and 5.2 KB per turn. That is above the fastest managed reference by a factor of 7.92, because every OneLLM run is a persisted instance with a snapshot, priced line items and events for each turn.

Floors, set at this first measurement and not to rise in later releases:

FloorValue
Per-turn save of a 200,000-token instance (append one turn, atomic file replace)7.22 ms, 4.39 MB allocated
Run with no hook (the eleven-turn run above)79.2 us, 56.8 KB

One observer hook on the message point adds about 0 us and 1.8 KB per run (78.6 us, 58.6 KB). Keeping the retained instance in memory costs 79.3 us per run. The same run with the file store, which writes the instance after every turn, takes 94.5 ms and 621 KB.

Other costs

RowMeanAllocated
Serialize a 200,000-token instance with one more turn544 us3.52 MB
Load a 200,000-token instance1.98 ms7.61 MB
Save a never-written 200,000-token instance1.86 ms5.54 MB
Template: plain text / field substitution / range and if / embed47 ns / 210 ns / 4.6 us / 309 ns
Template: cached parse lookup / cold parse55 ns / 7.6 us
Build the shipped catalog / build and resolve one model1.47 ms / 1.49 ms2.26 MB
Token count, core estimate, 1k / 50k / 200k tokens2.2 us / 58 us / 388 us

Core ships no local tokenizer; its count comes from the provider's endpoint when one exists and otherwise from the calibrated estimate timed above.

Conformance

Each feature of each provider, on each deployment that has one, is replayed from recorded fixtures: the request bytes OneLLM sends and the result it parses are both checked. Streaming and whole-response calls must build equal messages. The core test suite (1,304 tests: 1,239 passed, 65 skipped for platform reasons, 0 failed) includes all of these.

ProviderDeploymentFixture files replayedFailed
Anthropicfirst-party470
AnthropicAmazon Bedrock90
AnthropicVertex AI60
OpenAIfirst-party670
OpenAIAzure OpenAI70
GeminiGemini API570
GeminiVertex AI60
OpenAI-compatiblenine presets, two files each180

TypeSafe Jev is covered by the decider checks below. The Bedrock request signing passes the published SigV4 test suite, and the Vertex service-account token passes the published JWT vector.

Parity and round trips

The reference corpus of definitions and instances is a private collection kept on the build machine; only counts are reported.

CheckResult
Definition, flow, decider and instance files load and save without loss (extension data kept)5,473 files: 5,440 lossless, 0 lossy, 24 invalid input (a raw U+FEFF inside a block scalar), 9 removed during the run
Rendered prompts match the recorded rendering byte for byte600 sampled: 328 byte-equal, 271 not reproducible (scope not recorded, or sources changed since), 1 differing because the definition was edited after it was rendered; 0 engine differences
Template engine agrees with Go's text/template on generated templates (output and error class)12,858,638 templates in 1,680 s: 124 disagreements, of which 6 were fixed and 118 are documented differences (slices beyond the length but within capacity; strings cut mid-character)
Decider requests are byte-equal to the reference service's, and decide outputs agree336 of 336 requests byte-equal; outputs 144 of 144 for JavaScript logic and 144 of 144 for TypeScript logic; 35 of 35 TypeScript logic files load
Cost agrees with the reference calculator to the cent1,260 of 1,260 usages

Loop behaviour, security and AOT

CheckResult
Loop scenarios (termination, parallel calls in call order, approvals across a restart, steering, sub-agents, monitors, compaction pairing, cache-prefix stability), on the scripted provider and a fake clock93 agent tests, all passed
Capability-model review28 findings (CAP-1 to CAP-28), all closed; documented residue: detached children after a timeout with an open shell, hard links, an allow-list entry is not a sandbox, the cost of the git role rule
Sandbox review18 findings: 17 closed; one low (a burst of parallel hook-file loads across many definitions) bounded per owner and per definition, documented
NativeAOT publish of the sample apps (core: Ask, Ask<T>, an agent with generated tools, a file store; JavaScript; OneLite; the Microsoft.Extensions.AI bridge)0 warnings; all four run; the same samples also build and run in CI on Windows x64, Linux x64, Linux arm64 and macOS arm64
Fuzz targetsEvent-stream reader: 600 s, 47.4 million inputs, 0 findings. Template parser: 3.19 million inputs, 0 findings; the template differential above adds 12.86 million generated templates

Live runs

A small smoke against each provider's real API, run once at release under hard spend caps (tools/live-smoke.sh): chat, streaming, a client tool round trip, structured output, a reasoning model, embeddings, token counting and, for OpenAI, a Decisions call. Then each of the eight example agents ran its representative task once on an OpenAI and a Gemini model (tools/examples-e2e.sh). The first OpenAI smoke passed 7 of 8 (the Decisions case used a wrong model name, fixed in the tool); the second passed 8 of 8.

ProviderSmokeSpent in total (cap)
OpenAI8 of 8 cases passed$0.0264 ($0.90)
Gemini7 of 7 cases passed$0.198 ($0.45)
AnthropicNot run: no API key was available for the release checkn/a
Azure OpenAI / FoundryNot run: no Azure account; covered by recorded fixtures onlyn/a
Amazon BedrockNot run: no AWS account; covered by recorded fixtures and the published SigV4 test vectorsn/a
Vertex AINot run: no Google Cloud account; covered by recorded fixtures and the published JWT vectorn/a

Example agents, one run each. Outcome task_complete means the agent ended by calling task_complete; answered means it replied without calling it.

Example agentModelOutcomeTurnsCostSeconds
cs-tool-writergpt-5-nanoanswered2$0.00391277
js-tool-writergpt-5-nanotask_complete8$0.00362472
provider-writergpt-5-nanotask_complete5$0.00182842
agent-writergpt-5-nanoanswered1$0.00152335
script-writergpt-5-nanotask_complete1$0.00139832
decider-writergpt-5-nanoanswered4$0.00312364
hook-writergpt-5-nanoanswered1$0.00232251
orchestratorgpt-5-nanotask_complete13$0.007200130
cs-tool-writergemini-3.5-flash-litetask_complete26$0.03050327
js-tool-writergemini-3.5-flash-litetask_complete13$0.01668211
provider-writergemini-3.5-flash-litetask_complete19$0.02286515
agent-writergemini-3.5-flash-litetask_complete9$0.0113408
script-writergemini-3.5-flash-litetask_complete8$0.0093966
decider-writergemini-3.5-flash-litetask_complete16$0.02213417
hook-writergemini-3.5-flash-litetask_complete25$0.03372931
orchestratorgemini-3.5-flash-litetask_complete13$0.01619611

The Gemini cs-tool-writer row is its second attempt; the first stopped at its per-run spend cap after $0.0348, which is counted in the Gemini total above. A row is a full success when the agent calls task_complete, the files its task names exist, and its own checks passed (see the example agents); the answered rows are runs of the small OpenAI model that stopped without finishing the protocol.