Run it locally
This walks through running Relay on a developer machine.
#Prerequisites
- .NET 9 SDK
- SQL Server reachable with a connection string (LocalDB, a container, or a shared dev server), for the
relay_gatewayandidentitydatabases. - Qdrant (only if you use knowledge bases / RAG).
- ClickHouse (only if you want telemetry, dashboards and traces).
- An app registration in the company identity app, for signing in to the panel.
Windows note:
localhostresolves to IPv6::1, but containers (Docker/Podman) publish on IPv4. If a local service won't connect, use127.0.0.1instead oflocalhost.
Restore note: this environment cannot restore new NuGet packages, so every build and run command below passes
--no-restore. Only packages already in the local cache are used.
#1. Apply the database schema
Schema is a DACPAC (not EF migrations). Publish Application.Database to your relay_gateway database (via SqlPackage or Visual Studio's Publish). The apps do not run Database.Migrate() at startup, and the gateway selects recently added columns on every request, so publish before you run a new build.
#2. Configure connection strings and secrets
Use user-secrets or environment variables — never commit real secrets. See Configuration & secrets. The gateway needs:
dotnet user-secrets --project Application.Api set "ConnectionStrings:GatewayDb" "Server=127.0.0.1;Database=relay_gateway;..."
dotnet user-secrets --project Application.Api set "Encryption:MasterKey" "<base64, 32 bytes>"
The panel host needs the same GatewayDb and Encryption:MasterKey (the same value — it encrypts what the gateway decrypts), plus ConnectionStrings:UserManagementDb and the identity-app settings Identity:BaseUrl, Identity:ClientId and Identity:ClientSecret; it refuses to start without the secret.
#3. Run the apps
Either run all three under .NET Aspire, which starts them on their usual ports and opens a dashboard with their logs, traces and metrics (the login URL with its token is printed to the console):
dotnet run --project Application.AppHost --no-restore # dashboard → https://localhost:17300
Or run each app independently. Build in Release if you have other instances running (they can lock Debug DLLs):
# Public gateway API → http://localhost:5300 (https 7300)
dotnet run --project Application.Api --no-restore
# Control panel (host + WASM) → https://localhost:7236 (http 5198)
dotnet run --project Application --no-restore
# This documentation site → http://localhost:5400
dotnet run --project Application.Doc --no-restore
#4. Add a provider and models
In the control panel, add a Provider (e.g. OpenAI) and paste its API key — it is stored encrypted with Encryption:MasterKey and never shown again; a config SecretRef is an optional fallback for keys you would rather keep in configuration. Then add Models whose public alias maps to the provider's model id; the form can list what the provider serves and look up Azure prices. See Providers, Models and The panel, page by page.
#5. Issue an API key and make a call
Create a key under API Keys (the full key is shown once). Then:
curl http://localhost:5300/v1/chat/completions \
-H "Authorization: Bearer $RELAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "model": "gpt-4o", "messages": [{ "role": "user", "content": "Hello!" }] }'
That's it — you're through the gateway. Next, explore the API overview.
#Testing without a provider
For end-to-end checks without spending anything upstream, the gateway has a dev-only seed mode that creates a fixed test key and a provider pointed at a mock LLM server (one that speaks the OpenAI and Anthropic wire formats, JSON and SSE):
dotnet run --project Application.Api --no-restore -- --seed http://localhost:8899 # seed
dotnet run --project Application.Api --no-restore -- --unseed # tear down
The mock is more permissive than real providers, so anything about request validation — types, required fields, null handling — still needs a real endpoint to verify.