Recursive AI
LibraryC#Available

onellm

LLM inference and an agent runtime for .NET, in C#. One set of calls over Anthropic, OpenAI, Gemini and OpenAI-compatible servers, a price on every call, and agents, scripts and deciders as files you can run, save and resume.

Open source, MIT or Apache-2.0, made by Recursive AI. Version 1.0.0 is on NuGet.

dotnet add package RecursiveAI.OneLlm

A quick look

A model is a catalog name; the key comes from the environment. Every call returns its usage and a line-item cost, and an agent is a YAML file run with your C# tools.

The output shown is from a run on 1.0.0 with the library’s own scripted provider, priced from the shipped catalog. Getting started has the whole program.

Getting started
Program.csC#
string answer = await Llm.AskAsync("claude-sonnet",
    "In one sentence, what is a monad?");
 
AskResult r = await Llm.GenerateAsync("gpt-6-luna",
    "Name three prime numbers.", []);
Console.WriteLine($"{r.Text} [{r.Usage?.InputTokens} in, " +
    $"{r.Usage?.OutputTokens} out, {r.Cost.Total}]");
// 2, 3 and 5. [13 in, 7 out, 0.0000048]
 
// agents/clerk.yaml names get_docket, a [Tool] method
AgentResult a = await Llm.RunAgentAsync("agents/clerk.yaml",
    new Dictionary<string, object?> { ["caseNo"] = "24-1234" });
// Completed: Docket 24-1234 is open. (0.001730)
What it does

What it does

One set of calls

AskAsync, typed AskAsync<T> through the provider’s native structured output, StreamAsync, Chat and EmbedAsync, over one message model. Streamed events build the same message a whole call returns.

The happy path

Providers and deployments

Anthropic, OpenAI and Gemini, first-party and on Azure OpenAI / Foundry, Amazon Bedrock and Vertex AI, plus presets for Ollama, vLLM, LM Studio, OpenRouter, Groq, DeepSeek, xAI, Mistral and Together. No cloud SDK. Every row is tested from recorded fixtures; at release a live smoke ran against OpenAI and Gemini only, and Anthropic, Azure, Bedrock and Vertex were not run live.

Cloud deployments

A price on every call

Pricing is catalog data you can layer and override, with source URLs and asOf dates. Every result, tool call and instance carries decimal line items; an unpriced model costs zero with a warning, never a guess. Spend caps are checked before a call is sent.

Pricing and counting

Agents

The tool loop, with parallel calls returned in call order, approvals that survive a restart, steering, sub-agents, monitors and context strategies. Tools are C# methods marked [Tool]; a source generator writes the schema and an invoker with no reflection.

Agents

Scripts and deciders

A .flow file is prompts in order, one call each, written in Go’s text/template language. A decider asks typed choice, score and yes/no questions on TypeSafe Jev, OpenAI Decisions or any chat model.

Deciders

The host grants, not the file

Loading a definition never grants anything. The default is files under the working directory only; the host adds file roots, shell commands and network hosts. Sub-agents get at most their parent’s grants.

Capabilities

Every run is saved

Each call is an instance with its messages, usage and cost, kept in memory, as readable YAML files, in OneLite or through Entity Framework Core, so a chat or an agent can be listed, forked and resumed. JSONL and event record sinks, and OpenTelemetry GenAI spans and metrics.

Stores and sinks

Microsoft.Extensions.AI, both ways

OneLLM models as IChatClient, IEmbeddingGenerator and the speech and image clients, with cost in AdditionalProperties; any IChatClient as a OneLLM provider; AIFunction and ITool in both directions.

The bridge

The onellm tool

run, chat, instances, cost, catalog and examples from a shell, with grants as explicit flags and eight example agents built in.

The onellm tool
How it measures

Speed, plainly, and what was tested live

The project’s own measurements for 1.0 (not an external audit), with their method on the results page.

  • The agent loop is slower than the fastest managed reference, by a factor of 7.92, by design. An eleven-turn run on the scripted provider takes 78.2 µs and 56.8 KB, or 7.1 µs and 5.2 KB per turn. In the results page’s words: “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.”
  • Requests and streams, against a local mock server so the numbers are client code, not a network: a whole turn with a 1,000-token history in 35.9–50.0 µs; a 2,000-event stream read in 610.7–813.7 µs, depending on the provider.
  • Conformance is from recorded fixtures. In the results page’s words: “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.” 217 fixture files, 0 failed.
  • Live runs. A smoke against each real API under hard spend caps passed 8 of 8 on OpenAI and 7 of 7 on Gemini. Anthropic was “Not run: no API key was available for the release check”; Azure OpenAI / Foundry, Amazon Bedrock and Vertex AI were not run, for want of an account, and are “covered by recorded fixtures” only.
  • Cost and parity. Cost agrees with the reference calculator to the cent on 1,260 of 1,260 usages; on 12.86 million generated templates, the template engine and Go’s text/template disagreed 124 times: 6 fixed, 118 documented differences.
Every result, with method
Limits

Known gaps at 1.0.0

  • No live Anthropic, Azure, Bedrock or Vertex run. Those rows are tested from recorded fixtures (and, for Bedrock and Vertex, the published SigV4 and JWT test vectors) only.
  • Compatible-server quirks. From the OpenAI notes: “The quirks for Mistral and DeepSeek, the vLLM default port and reasoning-field names are recorded from the docs only partly and are to be checked against live servers.”
  • Token counts. “Core ships no local tokenizer”: a count comes from the provider’s endpoint when one exists, otherwise from a calibrated estimate.
  • Pricing. “Code-interpreter container sessions are not priced yet.”
  • Grants. From the capabilities page: “Not covered on any platform: hard links (see above), a detached process that survives its parent, and an allow-listed program that is itself an interpreter.”
What the grants cover

Status and packages

Go further

OneLLM is unaffiliated with the onellm package on PyPI and with the OneLLM research model.