---
title: "onellm"
url: https://recursiveai.org/onellm/
description: "LLM inference and an agent runtime for .NET, in C#: one set of calls over Anthropic, OpenAI, Gemini and OpenAI-compatible servers, a decimal price on every call, and agents, scripts and deciders as files you can run, save and resume. Open source, MIT or Apache-2.0. 1.0.0."
---

# 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.

```sh
dotnet add package RecursiveAI.OneLlm
```

- [Getting started](https://recursiveai.org/onellm/docs/getting-started/)
- [Docs](https://recursiveai.org/onellm/docs/)
- [GitHub](https://github.com/recursive-ai-oss/onellm-csharp)
- [NuGet](https://www.nuget.org/packages/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](https://recursiveai.org/onellm/docs/getting-started/)

*Program.cs · C#*

```
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)
```

### 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](https://recursiveai.org/onellm/docs/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](https://recursiveai.org/onellm/docs/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](https://recursiveai.org/onellm/docs/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](https://recursiveai.org/onellm/docs/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](https://recursiveai.org/onellm/docs/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](https://recursiveai.org/onellm/docs/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](https://recursiveai.org/onellm/docs/stores/)

### 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](https://recursiveai.org/onellm/docs/extensions-ai/)

### 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](https://recursiveai.org/onellm/docs/cli/)

## 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](https://recursiveai.org/onellm/docs/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](https://recursiveai.org/onellm/docs/results/)

## 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](https://recursiveai.org/onellm/docs/capabilities/)

## Status and packages

- **Core**: `RecursiveAI.OneLlm`: provider clients and deployments, the message model, catalog and pricing, templating, the runtime, agents, tools and their generator, deciders, file and memory stores, JSONL and event sinks, OpenTelemetry. Depends on OneYaml and OneImage; no native code.
- **Web**: `RecursiveAI.OneLlm.Web`: the `fetch_webpage_markdown` tool, on OneHtml.
- **JavaScript**: `RecursiveAI.OneLlm.JavaScript`: JavaScript tools, hooks and decider logic in a sandbox, and `run_javascript`, on OneEcma.
- **Extensions.AI**: `RecursiveAI.OneLlm.Extensions.AI`: the Microsoft.Extensions.AI bridge, both ways.
- **EF Core**: `RecursiveAI.OneLlm.EntityFrameworkCore`: an instance store and a record sink on your `DbContext`.
- **OneLite**: `RecursiveAI.OneLlm.OneLite`: an instance store and a record sink on a OneLite file.
- **Tool**: `RecursiveAI.OneLlm.Cli`, the `onellm` command: `dotnet tool install -g RecursiveAI.OneLlm.Cli`.
- **Status**: 1.0.0, all seven packages on one version. From the changelog: “The first public release.”
- **.NET**: .NET 10, C#. Trim and NativeAOT safe on the main paths: the sample apps publish with 0 warnings and run on Windows x64, Linux x64 and arm64, and macOS arm64. MIT or Apache-2.0.

## Go further

- [GitHub](https://github.com/recursive-ai-oss/onellm-csharp)
- [NuGet](https://www.nuget.org/packages/RecursiveAI.OneLlm)
- [Getting started](https://recursiveai.org/onellm/docs/getting-started/)
- [All docs](https://recursiveai.org/onellm/docs/)
- [Coming from another library](https://recursiveai.org/onellm/docs/reads-like/)
- [Results](https://recursiveai.org/onellm/docs/results/)
- [Changelog](https://recursiveai.org/onellm/docs/changelog/)

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