Augustus 0.8.0

dotnet add package Augustus --version 0.8.0
                    
NuGet\Install-Package Augustus -Version 0.8.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Augustus" Version="0.8.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Augustus" Version="0.8.0" />
                    
Directory.Packages.props
<PackageReference Include="Augustus" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Augustus --version 0.8.0
                    
#r "nuget: Augustus, 0.8.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Augustus@0.8.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Augustus&version=0.8.0
                    
Install as a Cake Addin
#tool nuget:?package=Augustus&version=0.8.0
                    
Install as a Cake Tool

Augustus

A modular API simulator library for .NET. Serve static JSON, load from files, or generate realistic responses with AI — all from a lightweight local web server in your tests.

NuGet Augustus NuGet Augustus.AI NuGet Augustus.AI.Reqnroll .NET License

Packages

Package Purpose AI Required?
Augustus Core simulator — static JSON, file-based, and custom response strategies with route matching No
Augustus.AI AI-powered response generation and real-API proxy mode via OpenAI Yes
Augustus.APIs.Stripe Pre-built Stripe API defaults and fluent helpers No
Augustus.Reqnroll Reqnroll (BDD) integration with per-scenario cache isolation No

Quick Start

Manual mocks only (no AI, no API key)

dotnet add package Augustus
using Augustus.Extensions;

public class StripeTests
{
    [Fact]
    public async Task Should_Return_Customer_Data()
    {
        var simulator = this.CreateAPISimulator("Stripe")
            .ForGet("/v1/customers/{id}")
                .WithJsonFile("./mocks/customer.json")
                .Add()
            .ForPost("/v1/charges")
                .WithResponse(new { id = "ch_123", amount = 2000, currency = "usd", status = "succeeded" })
                .Add();

        await simulator.StartAsync();

        var client = simulator.CreateClient();
        var response = await client.GetAsync("/v1/customers/cus_123");

        response.StatusCode.Should().Be(HttpStatusCode.OK);
        var content = await response.Content.ReadAsStringAsync();
        content.Should().Contain("cus_123");

        await simulator.StopAsync();
    }
}

AI default handler for unmatched routes

dotnet add package Augustus.AI
using Augustus.AI;
using Augustus.Extensions;

public class StripeTests
{
    [Fact]
    public async Task Should_Return_Customer_Data()
    {
        var simulator = this.CreateStripeSimulator(opt => opt.Port = 0);
        simulator.UseAI(new AIOptions
        {
            OpenAIApiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!
        });

        // Static override — always served from this JSON
        simulator.ForGet("/v1/customers/cus_known")
            .WithResponse(new { id = "cus_known", name = "John Doe" })
            .Add();

        // Everything else handled by AI
        simulator.AddInstruction("Return realistic Stripe API responses");

        await simulator.StartAsync();
        var client = simulator.CreateClient();

        // Hits the static route
        var known = await client.GetStringAsync("/v1/customers/cus_known");
        known.Should().Contain("John Doe");

        // Falls through to AI
        var generated = await client.GetStringAsync("/v1/customers/cus_other");
        generated.Should().Contain("cus_other");

        await simulator.StopAsync();
    }
}

Per-route AI

using Augustus.AI;

simulator.ForGet("/v1/payments/{id}")
    .UseAI(aiOptions, "Return a completed payment object")
    .Add();

simulator.ForPost("/v1/payments")
    .WithResponse(new { id = "pay_static", status = "pending" })
    .Add();

Route Resolution

Requests are resolved in this order:

  1. Route with strategy — execute the matched IResponseStrategy (static, file, AI, or custom)
  2. Default handler — delegate to the AI or proxy handler (if installed via UseAI / UseProxy)
  3. No match, no default handler — HTTP 404 JSON error

Configuration

Core options (APISimulatorOptions)

var simulator = this.CreateAPISimulator("MyAPI", options =>
{
    options.Port = 0;                        // 0 = auto-assign (default: 9001)
    options.EnableCaching = true;            // Cache AI/proxy responses (default: true)
    options.CacheFolderPath = "./mocks";     // Where cache files live (default: ./mocks)
    options.CacheOnly = false;               // Serve only from cache, 503 on miss (default: false)
    options.AutoRemoveStaleCache = true;     // Clean up untouched cache files on dispose (default: true)
});

AI options (AIOptions — Augustus.AI package)

simulator.UseAI(new AIOptions
{
    OpenAIApiKey = "sk-...",                 // Required (unless CacheOnly)
    OpenAIModel = "gpt-4o-mini",            // Default: gpt-4o-mini
    OpenAIEndpoint = "",                     // Optional: custom endpoint
    UseAzureOpenAI = false,                  // Use Azure OpenAI service
    AzureDeploymentName = "",                // Required when UseAzureOpenAI = true
    AzureApiVersion = "2024-06-01",          // Azure API version
    MaxRetries = 5,                          // Retry attempts for transient failures
    MaxConcurrentRequests = 10               // Process-wide concurrent OpenAI limit (see below)
});

OpenAI rate limits and call efficiency

Augustus.AI reduces duplicate traffic and 429 rate-limit pressure in several ways:

  • Shared throttling — For a given API key (or Azure endpoint + key), model/deployment, and MaxConcurrentRequests value, all OpenAI chat completions in the process share one concurrency gate. This applies across the default UseAI handler and route-level UseAI, so parallel test classes do not each get a full MaxConcurrentRequests budget in isolation.
  • In-flight deduplication — Concurrent requests that resolve to the same cache key (same method, path, query, normalized body, and route instructions) share a single in-flight OpenAI completion instead of fanning out.
  • Retries — Transient failures (429, 5xx) use exponential backoff with jitter. When the service returns a Retry-After header, the delay respects it (in addition to backoff caps from InitialRetryDelayMs / MaxRetryDelayMs).
  • Proxy / UseRealApi — Upstream HTTP calls retry on 429 and 5xx with the same delay settings; global DynamicContentFields from APISimulatorOptions are merged with per-route WithDynamicFields for cache keys.
  • Practical tips — For first-time cache generation, prefer a low MaxConcurrentRequests (for example 12) and/or run tests serially so retries do not multiply billed attempts. Use cache-only CI (CacheOnly / committed mocks) so CI never calls OpenAI.

Response Strategies

Static JSON

simulator.ForGet("/api/health")
    .WithResponse(new { status = "ok" })
    .WithStatusCode(200)
    .Add();

JSON file

simulator.ForGet("/v1/customers/{id}")
    .WithJsonFile("./mocks/customer.json")
    .Add();

Custom strategy

simulator.ForPost("/api/echo")
    .WithStrategy(new MyCustomStrategy())
    .Add();

AI-generated (Augustus.AI)

Route-level UseAI uses the same structured cache keys as the default AI handler (CacheKeyComputer), stores entries in the simulator’s cache folder, and still reads legacy curl-based cache files if present. Azure OpenAI is supported on routes the same way as simulator.UseAI(...).

simulator.ForGet("/v1/payments/{id}")
    .UseAI(aiOptions, "Return a completed payment with realistic fields")
    .Add();

Real API proxy (Augustus.AI)

simulator.ForPost("/v1/chat/completions")
    .UseRealApi("https://api.openai.com", apiKey, aiOptions)
    .Add();

Extension Methods

// Core (Augustus package) — no AI dependency
var sim = this.CreateAPISimulator("MyAPI");
var stripe = this.CreateStripeSimulator();
var paypal = this.CreatePayPalSimulator();

// AI-powered (Augustus.AI package)
var openai = this.CreateOpenAISimulator(opt => { opt.OpenAIApiKey = key; });
var azure = this.CreateAzureOpenAISimulator(opt => { ... });

// Proxies (Augustus.AI package)
var proxy = this.CreateOpenAIProxy(opt => { opt.OpenAIApiKey = key; });
var azureProxy = this.CreateAzureOpenAIProxy(opt => { ... });

Pass-Through Proxy Mode

Forward requests to a real upstream API, cache responses, and replay on subsequent calls. Ideal for tool/function calling scenarios.

var simulator = this.CreateAPISimulator("OpenAI Proxy");
simulator.UseProxy(
    new AIOptions
    {
        OpenAIApiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!
    },
    upstreamUrl: "https://api.openai.com"
);
await simulator.StartAsync();

var client = simulator.CreateClient();
// First call: forwarded to real API, response cached
// Second call: served from cache instantly
var response = await client.PostAsync("/v1/chat/completions", content);

Cache-Only Mode

Replay cached responses without an API key or network — perfect for CI/CD.

var simulator = this.CreateAPISimulator("Stripe", options =>
{
    options.CacheOnly = true;
    options.CacheFolderPath = "./pre-recorded-mocks";
});
await simulator.StartAsync();
// Returns cached responses or HTTP 503 on cache miss

Reqnroll (BDD) Integration

dotnet add package Augustus.Reqnroll
using Augustus.AI;
using Augustus.Extensions;
using Augustus.Reqnroll;
using Reqnroll;

[Binding]
public class Hooks
{
    private static APISimulator? _simulator;

    [BeforeTestRun]
    public static async Task BeforeTestRun()
    {
        _simulator = new Hooks().CreateStripeSimulator();
        _simulator.UseAI(new AIOptions
        {
            OpenAIApiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!
        });
        _simulator.AddInstruction("Return realistic Stripe API responses");

        AugustusReqnrollContext.Register(_simulator);
        await _simulator.StartAsync();
    }
}

Cached responses are organized per scenario:

Features/
  __mocks__/
    Stripe/
      Scenario_Name_1/
        {hash}.json
      Scenario_Name_2/
        {hash}.json
  MyFeature.feature

Caching

Cache file names and RequestHash are derived from the HTTP method, path, query string, and a canonical form of JSON request bodies (sorted object keys at every depth, plus optional DynamicContentFields normalization). Non-JSON bodies use raw bytes. See CHANGELOG.md for release notes when this algorithm changes — upgrades can invalidate existing on-disk caches.

Augustus caches responses as JSON files:

{
  "RequestHash": "A1B2C3D4E5F6G7H8",
  "Response": "{\"id\": \"cus_123\", \"name\": \"John Doe\"}",
  "OriginalRequest": "curl -X GET http://localhost:9001/v1/customers/cus_123",
  "Instructions": ["You are a Stripe API simulator"],
  "Timestamp": "2024-01-15T10:30:00Z"
}
simulator.ClearCache();                    // Clear all cached responses
simulator.SetTestContext("my-scenario");   // Route cache to a subdirectory
simulator.ClearTestContext();              // Clear subdirectory and remove stale entries

Package Dependency Graph

Augustus (core) — no OpenAI dependency
  └── Microsoft.AspNetCore.App (framework ref only)

Augustus.AI → Augustus
  ├── OpenAI (2.9.1)
  └── Azure.AI.OpenAI (2.1.0)

Augustus.APIs.Stripe → Augustus

Augustus.Reqnroll → Augustus
  └── Reqnroll packages

Best Practices

  1. Start with static mocks — use WithResponse / WithJsonFile for deterministic tests; add AI only where needed
  2. Use Port = 0 — auto-assign ports to avoid conflicts in parallel test runs
  3. Enable caching — dramatically speeds up AI-powered tests and reduces API costs
  4. Use cache-only in CI — commit cached responses and run without an API key
  5. Use await using — ensures proper cleanup of the simulator's web server
  6. Proxy mode for tool calling — when testing function/tool calling, use proxy mode to get real model reasoning

Building from Source

git clone https://github.com/chrisjainsley/augustus.git
cd augustus
dotnet build
dotnet test

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

If you encounter any issues or have questions:

  1. Search existing issues
  2. Create a new issue if needed

Roadmap

  • Route-based response dispatch with pluggable strategies
  • AI-powered response generation via OpenAI (Augustus.AI)
  • Pass-through proxy mode with response caching
  • Cache-only mode for CI/offline testing
  • BDD integration (Reqnroll)
  • Dynamic port assignment for parallel testing
  • More API-specific packages (PayPal, Twilio, etc.)
  • Support for more AI providers (Anthropic Claude, Google Gemini)
  • Request/response validation
  • Docker support
Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net6.0

    • No dependencies.
  • net7.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on Augustus:

Package Downloads
Augustus.AI

OpenAI-powered extension for Augustus. Generates realistic API responses using AI and supports proxying to real APIs with caching.

Augustus.Stripe

Stripe-specific extensions for Augustus. Provides fluent API for mocking Stripe endpoints with built-in realistic defaults.

Augustus.Reqnroll

Reqnroll integration for Augustus API simulator. Automatically places mock caches next to feature files and organizes by scenario.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.8.0 233 3/28/2026
0.7.0 166 3/23/2026
0.6.0 153 3/22/2026
0.5.2 155 3/22/2026
0.5.1 167 3/20/2026
0.5.0 102 3/20/2026