Back to "LLMApi: Modular Architecture Examples"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

AI AI-Article API ASP.NET Core LLM LLMApi mockllmapi Nuget

LLMApi: Modular Architecture Examples

Sunday, 02 November 2025

Introduction

One of the key things I wanted with LLMApi was the ability for it to be as lightweight as possible (so JUST simulate the api type you want) AND be super easy to get intp; so you should be able to get EVERYTHING just as easily. With this in mind I designed it with modularity in mind (whispers..in future I want you to be able to add 'plugins' which enable even more). Here's the article on how tha tarchitecture works and all it's ins and outs.

You can find the GitHub here for the project, all public domain etc...

NOTE: This is the live from gitHub. It is AI generated.

NuGet NuGet

You can find the GitHub here for the project, all public domain etc...

Modular Architecture Examples

New in v1.2.0: Complete modularity! Each protocol (REST, Streaming, GraphQL, SignalR) can now be added and mapped independently.

Table of Contents


Backward Compatible (Unified Approach)

Existing code continues to work without any changes:

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Registers ALL services (REST, Streaming, GraphQL)
builder.Services.AddLLMockApi(builder.Configuration);

// Optional: Add SignalR
builder.Services.AddLLMockSignalR(builder.Configuration);

builder.Services.AddRazorPages();

var app = builder.Build();

app.UseStaticFiles();
app.UseRouting();
app.MapRazorPages();

// Maps ALL endpoints (REST, Streaming, GraphQL) at /api/mock
app.MapLLMockApi("/api/mock", includeStreaming: true, includeGraphQL: true);

// Optional: Map SignalR
app.MapLLMockSignalR("/hub/mock", "/api/mock");

app.Run();

This creates:

  • /api/mock/** - REST endpoints
  • /api/mock/stream/** - SSE streaming endpoints
  • /api/mock/graphql - GraphQL endpoint
  • /hub/mock - SignalR hub (if added)
  • /api/mock/contexts - SignalR management API (if added)

Modular Approach

REST Only

Perfect for simple REST API mocking without extra overhead:

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register ONLY REST services
builder.Services.AddLLMockRest(builder.Configuration);

var app = builder.Build();

app.UseRouting();

// Map ONLY REST endpoints
app.MapLLMockRest("/api/mock");

app.Run();

This creates:

  • /api/mock/** - REST endpoints only

Benefits:

  • Minimal memory footprint
  • Faster startup time
  • Only includes RegularRequestHandler

GraphQL Only

Perfect for GraphQL-only applications:

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register ONLY GraphQL services
builder.Services.AddLLMockGraphQL(builder.Configuration);

var app = builder.Build();

app.UseRouting();

// Map ONLY GraphQL endpoint
app.MapLLMockGraphQL("/api/mock");

app.Run();

This creates:

  • /api/mock/graphql - GraphQL endpoint only

Benefits:

  • Clean GraphQL-only setup
  • No unnecessary REST handlers
  • Perfect for GraphQL client testing

Streaming Only

Perfect for testing SSE streaming clients:

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register ONLY Streaming services
builder.Services.AddLLMockStreaming(builder.Configuration);

var app = builder.Build();

app.UseRouting();

// Map ONLY Streaming endpoints
app.MapLLMockStreaming("/api/mock");

app.Run();

This creates:

  • /api/mock/stream/** - SSE streaming endpoints only

Benefits:

  • Lightweight streaming-only setup
  • Perfect for EventSource testing
  • No REST/GraphQL overhead

SignalR Only

Perfect for real-time dashboard prototyping:

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register ONLY SignalR services (includes core services automatically)
builder.Services.AddLLMockSignalR(options =>
{
    options.BaseUrl = "http://localhost:11434/v1/";
    options.ModelName = "llama3";
    options.SignalRPushIntervalMs = 5000;
});

var app = builder.Build();

app.UseRouting();

// Map ONLY SignalR endpoints
app.MapLLMockSignalR("/hub/mock", "/api/contexts");

app.Run();

This creates:

  • /hub/mock - SignalR hub
  • /api/contexts - Context management API

Benefits:

  • Real-time only setup
  • No HTTP endpoint overhead
  • Perfect for WebSocket testing

gRPC Only

Perfect for testing gRPC clients with dynamic proto definitions:

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register services (gRPC included in AddLLMockApi)
builder.Services.AddLLMockApi(builder.Configuration);

var app = builder.Build();

app.UseRouting();

// Map ONLY gRPC endpoints
app.MapLLMockGrpcManagement("/api/grpc-protos");  // Proto file management
app.MapLLMockGrpc("/api/grpc");                   // gRPC service calls

app.Run();

This creates:

  • /api/grpc-protos - Upload/manage .proto files (POST, GET, DELETE)
  • /api/grpc/{serviceName}/{methodName} - Invoke mock gRPC methods

Benefits:

  • Dynamic proto upload without recompilation
  • Perfect for gRPC client testing
  • LLM generates realistic protobuf responses

Usage example:

# 1. Upload a proto definition
curl -X POST http://localhost:5116/api/grpc-protos \
  -H "Content-Type: text/plain" \
  --data 'syntax = "proto3"; service UserService { rpc GetUser(GetUserRequest) returns (User); }'

# 2. Call the gRPC method
curl -X POST http://localhost:5116/api/grpc/UserService/GetUser \
  -H "Content-Type: application/json" \
  -d '{"user_id": 123}'

OpenAPI Only

Perfect for mocking existing OpenAPI/Swagger specs:

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register ONLY OpenAPI services
builder.Services.AddLLMockOpenApi(options =>
{
    options.BaseUrl = "http://localhost:11434/v1/";
    options.ModelName = "llama3";
    options.OpenApiSpecs = new List<OpenApiSpecConfig>
    {
        new OpenApiSpecConfig
        {
            Name = "PetStore",
            Source = "https://petstore3.swagger.io/api/v3/openapi.json",
            BasePath = "/api/petstore"
        }
    };
});

var app = builder.Build();

app.UseRouting();

// Map ONLY OpenAPI endpoints
app.MapLLMockOpenApi();                      // Loads configured specs
app.MapLLMockOpenApiManagement("/api/specs"); // Dynamic spec management

app.Run();

This creates:

  • All endpoints defined in your OpenAPI spec (e.g., /api/petstore/pet/{petId})
  • /api/specs - Upload/manage OpenAPI specs dynamically (POST, GET, DELETE)

Benefits:

  • Automatically mock entire OpenAPI specs
  • No manual endpoint mapping required
  • Supports both static (configured) and dynamic (uploaded) specs
  • Perfect for API contract testing

Context Management API

Add context history viewing and modification:

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register REST services
builder.Services.AddLLMockRest(builder.Configuration);

var app = builder.Build();

app.UseRouting();

// Map REST endpoints
app.MapLLMockRest("/api/mock");

// Add context management API
app.MapLLMockApiContextManagement("/api/contexts");

app.Run();

This creates:

  • /api/mock/** - REST endpoints
  • /api/contexts/{contextId} - View/modify conversation history

Benefits:

  • View LLM conversation history for debugging
  • Modify context to steer responses
  • Clear context to reset state
  • Perfect for testing stateful scenarios

Mix and Match

Combine protocols as needed for your use case:

Example 1: REST + GraphQL (No Streaming)

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register REST and GraphQL services
builder.Services.AddLLMockRest(builder.Configuration);
builder.Services.AddLLMockGraphQL(builder.Configuration);

var app = builder.Build();

app.UseRouting();

// Map both protocols
app.MapLLMockRest("/api/mock");
app.MapLLMockGraphQL("/api/mock");

app.Run();

This creates:

  • /api/mock/** - REST endpoints
  • /api/mock/graphql - GraphQL endpoint
  • No streaming endpoints

Example 2: GraphQL + SignalR (No REST)

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register GraphQL and SignalR services
builder.Services.AddLLMockGraphQL(builder.Configuration);
builder.Services.AddLLMockSignalR(builder.Configuration);

var app = builder.Build();

app.UseRouting();

// Map both protocols
app.MapLLMockGraphQL("/api/queries");
app.MapLLMockSignalR("/hub/realtime", "/api/contexts");

app.Run();

This creates:

  • /api/queries/graphql - GraphQL endpoint
  • /hub/realtime - SignalR hub
  • /api/contexts - SignalR management API
  • No REST or SSE endpoints

Example 3: Everything with Different Patterns

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register all services modularly
builder.Services.AddLLMockRest(builder.Configuration);
builder.Services.AddLLMockStreaming(builder.Configuration);
builder.Services.AddLLMockGraphQL(builder.Configuration);
builder.Services.AddLLMockSignalR(builder.Configuration);

var app = builder.Build();

app.UseRouting();

// Map each protocol with custom patterns
app.MapLLMockRest("/api/rest");           // /api/rest/**
app.MapLLMockStreaming("/api/stream");    // /api/stream/stream/**
app.MapLLMockGraphQL("/api/graphql");     // /api/graphql/graphql
app.MapLLMockSignalR("/hub/live", "/api/hub");

app.Run();

This creates:

  • /api/rest/** - REST endpoints
  • /api/stream/stream/** - SSE streaming
  • /api/graphql/graphql - GraphQL endpoint
  • /hub/live - SignalR hub
  • /api/hub/contexts - SignalR management

Example 4: REST + OpenAPI + Context Management

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register REST and OpenAPI services
builder.Services.AddLLMockRest(builder.Configuration);
builder.Services.AddLLMockOpenApi(builder.Configuration);

var app = builder.Build();

app.UseRouting();

// Map all three capabilities
app.MapLLMockRest("/api/mock");
app.MapLLMockOpenApi();
app.MapLLMockApiContextManagement("/api/contexts");

app.Run();

This creates:

  • /api/mock/** - REST endpoints
  • OpenAPI spec endpoints (from configured specs)
  • /api/contexts/{contextId} - Context management
  • No streaming, GraphQL, SignalR, or gRPC

Example 5: gRPC + OpenAPI (Protocol Bridge Testing)

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register services for both protocols
builder.Services.AddLLMockApi(builder.Configuration);  // Includes gRPC
builder.Services.AddLLMockOpenApi(builder.Configuration);

var app = builder.Build();

app.UseRouting();

// Map both protocols
app.MapLLMockGrpcManagement("/api/grpc-protos");
app.MapLLMockGrpc("/api/grpc");
app.MapLLMockOpenApi();

app.Run();

This creates:

  • /api/grpc-protos - gRPC proto management
  • /api/grpc/{service}/{method} - gRPC calls
  • OpenAPI spec endpoints
  • Perfect for testing protocol bridges/gateways

Example 6: Everything Modular (Full Stack Testing)

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Register everything modularly
builder.Services.AddLLMockRest(builder.Configuration);
builder.Services.AddLLMockStreaming(builder.Configuration);
builder.Services.AddLLMockGraphQL(builder.Configuration);
builder.Services.AddLLMockSignalR(builder.Configuration);
builder.Services.AddLLMockOpenApi(options =>
{
    options.BaseUrl = "http://localhost:11434/v1/";
    options.ModelName = "llama3";
    options.OpenApiSpecs = new List<OpenApiSpecConfig>
    {
        new OpenApiSpecConfig
        {
            Name = "External API",
            Source = "https://api.example.com/openapi.json",
            BasePath = "/api/external"
        }
    };
});

var app = builder.Build();

app.UseRouting();

// Map everything at different paths
app.MapLLMockRest("/api/rest");
app.MapLLMockStreaming("/api/stream");
app.MapLLMockGraphQL("/api/graphql");
app.MapLLMockSignalR("/hub/realtime", "/api/hub");
app.MapLLMockOpenApi();
app.MapLLMockOpenApiManagement("/api/specs");
app.MapLLMockGrpcManagement("/api/grpc-protos");
app.MapLLMockGrpc("/api/grpc");
app.MapLLMockApiContextManagement("/api/contexts");

app.Run();

This creates:

  • /api/rest/** - REST endpoints
  • /api/stream/stream/** - SSE streaming
  • /api/graphql/graphql - GraphQL endpoint
  • /hub/realtime - SignalR hub
  • /api/hub/contexts - SignalR management
  • /api/external/** - OpenAPI spec endpoints
  • /api/specs - OpenAPI management
  • /api/grpc-protos - gRPC proto management
  • /api/grpc/{service}/{method} - gRPC calls
  • /api/contexts/{contextId} - Context management

Perfect for:

  • Comprehensive integration testing
  • Testing microservice architectures
  • Multi-protocol API gateways
  • Full-stack development with various client types

Multiple Instances

Run multiple independent mock APIs with different configurations:

using mostlylucid.mockllmapi;

var builder = WebApplication.CreateBuilder(args);

// Development endpoints - high randomness
builder.Services.AddLLMockRest(options =>
{
    options.BaseUrl = "http://localhost:11434/v1/";
    options.ModelName = "llama3";
    options.Temperature = 1.5;
});

builder.Services.AddLLMockGraphQL(options =>
{
    options.BaseUrl = "http://localhost:11434/v1/";
    options.ModelName = "llama3";
    options.Temperature = 1.5;
});

var app = builder.Build();

app.UseRouting();

// Development endpoints
app.MapLLMockRest("/api/dev");
app.MapLLMockGraphQL("/api/dev");

// Stable test endpoints (would need separate config)
app.MapLLMockRest("/api/test");
app.MapLLMockGraphQL("/api/test");

app.Run();

Benefits of Modular Approach

1. Reduced Memory Footprint

Only load the handlers you actually use:

  • REST only: ~30% less memory
  • GraphQL only: ~40% less memory
  • Streaming only: ~40% less memory

2. Faster Startup

Fewer services to register = faster app startup

3. Clearer Intent

Code explicitly shows which protocols your app uses

4. Easier Testing

Test protocols in isolation:

// Test file for REST only
builder.Services.AddLLMockRest(config);
app.MapLLMockRest("/api/mock");

// Test file for GraphQL only
builder.Services.AddLLMockGraphQL(config);
app.MapLLMockGraphQL("/api/mock");

5. No Breaking Changes

Existing code continues to work:

// This still works exactly as before
builder.Services.AddLLMockApi(configuration);
app.MapLLMockApi("/api/mock");

6. Flexible Patterns

Mount protocols at any path:

app.MapLLMockRest("/rest");
app.MapLLMockGraphQL("/gql");
app.MapLLMockStreaming("/events");
app.MapLLMockSignalR("/ws", "/manage");

Migration Guide

From v1.1.0 to v1.2.0

No changes required! Your existing code works as-is.

Optional: Migrate to modular approach for benefits

Before (v1.1.0):

builder.Services.AddLLMockApi(builder.Configuration);
app.MapLLMockApi("/api/mock", includeStreaming: true, includeGraphQL: true);

After (v1.2.0 - Modular):

// Only include what you need
builder.Services.AddLLMockRest(builder.Configuration);
builder.Services.AddLLMockGraphQL(builder.Configuration);

app.MapLLMockRest("/api/mock");
app.MapLLMockGraphQL("/api/mock");

Both approaches work identically, but the modular approach is more explicit and efficient.


Summary

Core Protocol Services

Approach Add Method Map Method Use Case
Unified AddLLMockApi() MapLLMockApi() Everything (REST+Streaming+GraphQL+gRPC), backward compatible
REST AddLLMockRest() MapLLMockRest() Simple REST mocking
GraphQL AddLLMockGraphQL() MapLLMockGraphQL() GraphQL-only apps
Streaming AddLLMockStreaming() MapLLMockStreaming() SSE streaming only
SignalR AddLLMockSignalR() MapLLMockSignalR() Real-time WebSocket data
OpenAPI AddLLMockOpenApi() MapLLMockOpenApi() Mock from OpenAPI/Swagger specs

Additional Features (No Add Method Required)

Feature Map Method Use Case
gRPC Management MapLLMockGrpcManagement() Upload/manage .proto files
gRPC Calls MapLLMockGrpc() Invoke mock gRPC methods
OpenAPI Management MapLLMockOpenApiManagement() Dynamically load OpenAPI specs
Context Management MapLLMockApiContextManagement() View/modify LLM conversation history

Notes:

  • gRPC services are included in AddLLMockApi() but map separately
  • OpenAPI management allows dynamic spec loading at runtime
  • Context management works with any protocol that maintains conversation state
  • All features can be mixed and matched as needed

Choose the approach that best fits your needs!

logo

© 2025 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.