Skip to content

encryptedtouhid/et-complete-agent

Complete Agent — Microsoft Agent Framework Template

CI NuGet version NuGet pre-release NuGet downloads License: MIT .NET 10

A production-grade dotnet new template for building AI agents on Microsoft Agent Framework in .NET 10.

Generates a Clean-Architecture solution with everything a real deployment needs: dependency injection, validated configuration, versioned prompts, function tools, RAG, conversation memory, content moderation, cost budgeting, JWT + API-key auth, distributed rate limiting, OpenTelemetry, retries, health checks, structured JSON output, streaming, plus Docker and Kubernetes manifests.


Quick start

# 1. Install the template
dotnet new install EncryptedTouhid.AgentFramework.Templates

# 2. Generate a new solution
dotnet new et-complete-agent -n CompleteAgent
cd CompleteAgent

# 3. Set a provider + API key (Azure OpenAI shown below)
dotnet user-secrets set "Agent:AzureOpenAI:Endpoint" "https://<resource>.openai.azure.com" \
    --project src/EncryptedTouhid.CompleteAgent.Host
az login   # DefaultAzureCredential picks this up

# 4. Set an API key for your agent endpoint
dotnet user-secrets set "Authentication:ApiKey" "$(openssl rand -hex 16)" \
    --project src/EncryptedTouhid.CompleteAgent.Host

# 5. Run
dotnet run --project src/EncryptedTouhid.CompleteAgent.Host
# Call the agent
curl -X POST http://localhost:5000/agent/run \
  -H "X-API-Key: <your-key>" \
  -H "Content-Type: application/json" \
  -d '{"input": "Summarise Clean Architecture in two sentences."}'

What you get

CompleteAgent/
├── CompleteAgent.sln
├── Dockerfile                                Multi-stage, distroless, non-root
├── docker-compose.yml                        Agent + Redis + Qdrant for local dev
├── deploy/k8s/                               Namespace, Deployment, HPA, NetworkPolicy, ...
├── src/
│   ├── EncryptedTouhid.CompleteAgent.Domain/                    Contracts, value records (zero deps)
│   ├── EncryptedTouhid.CompleteAgent.Application/               Runner, tools, workflows, sanitiser, retry
│   ├── EncryptedTouhid.CompleteAgent.Infrastructure/            LLM client, EF Core, Qdrant, moderation
│   └── EncryptedTouhid.CompleteAgent.Host/                      Program.cs, endpoints, auth, telemetry
└── tests/
    └── EncryptedTouhid.CompleteAgent.Application.Tests/         xUnit + NSubstitute + FakeTimeProvider

All assemblies use the EncryptedTouhid.<ProjectName>.* namespace convention. The EncryptedTouhid. prefix is the org marker and stays fixed; the middle segment is whatever you pass to dotnet new -n.


Feature inventory

Agent core

LLM providers Azure OpenAI (DefaultAzureCredential) and OpenAI (OPENAI_API_KEY), switchable at runtime
Function tools GetCurrentTimeTool, SearchKnowledgeBaseTool, RetrieveDocumentsTool (RAG) — extend via AIFunctionFactory.Create
Workflow ResearchAndSummariseWorkflow (multi-agent pipeline)
Streaming IAsyncEnumerable<string> runner + SSE HTTP endpoint
Structured output Sentiment classifier endpoint returning typed JSON
Conversation memory IConversationStore with eight backings: InMemory, Sqlite, SqlServer, AzureSql, Postgres, MySql, Cosmos, Mongo. TTL + message cap honoured per provider, matching IAuditLog impl ships per backend
RAG IDocumentRetriever with InMemory cosine-similarity + Qdrant gRPC implementations
Versioned prompts src/<Name>.Host/Prompts/v1/{system,guardrails,examples}.md — bump to v2/ for a roll

Safety & policy

Input sanitisation InputSanitiser delimits and escapes user input to mitigate prompt injection
Output guardrail OutputGuardrail scrubs emails, secrets, phone numbers from agent responses
Content moderation IContentModerator abstraction with no-op default + Azure AI Content Safety implementation
PII-safe logging PromptRedactor truncates and redacts before logs; source-gen LoggerMessage everywhere
Prompt evals Golden-set tests verifying prompt structure and absence of leaked secrets

Platform & ops

Authentication X-API-Key middleware (constant-time compare) + optional JWT bearer (Entra ID / Auth0 / Okta)
Authorization AgentAccess policy — requires JWT when enabled, open when not
Rate limiting Per-key fixed window — in-memory default, Redis Lua-script for multi-instance
Cost budget Per-key daily token cap, returns 402 Payment Required when exceeded
Retries Exponential backoff on HttpRequestException, TimeoutException
Telemetry OpenTelemetry traces + metrics, OTLP + console exporters, instruments Microsoft.Agents.AI, ASP.NET Core, HttpClient
Health checks /healthz (liveness), /readyz (validates LLM config is present)
OpenAPI MapOpenApi() exposes the schema; wire your Swagger UI of choice

Engineering quality

Architecture Strict Clean Architecture: Domain ← Application ← Infrastructure ← Host
DI Microsoft.Extensions.DependencyInjection throughout; layer-scoped Add* extensions
Config Options pattern with DataAnnotations + IValidatableObject + ValidateOnStart
Analyzers NetAnalyzers, SonarAnalyzer.CSharp, SecurityCodeScan.VS2019
Build hygiene TreatWarningsAsErrors=true, nullable enabled, implicit usings, central package versioning
Tests xUnit + NSubstitute + FakeTimeProvider — all MIT/Apache, zero commercial libraries
AOT-friendly JSON JsonSerializerContext source-gen for endpoint DTOs

HTTP API surface

Method Path Description
POST /agent/run Single-turn request. Auto-persists turn when conversationId is supplied.
POST /agent/stream Server-Sent Events stream of agent output.
POST /agent/classify Structured-output example returning typed sentiment JSON.
DELETE /agent/conversations/{conversationId} Wipes a stored conversation.
GET /healthz Liveness — bypasses auth and rate limiting.
GET /readyz Readiness — validates LLM provider configuration.
GET /openapi/v1.json OpenAPI schema (raw JSON).
GET /scalar Interactive API explorer (Scalar UI, GitHub-themed, dark/light auto).

Request body for /agent/run and /agent/stream:

{ "input": "...", "conversationId": "optional-uuid" }

Configuration

Every knob lives in appsettings.json (or env vars prefixed COMPLETEAGENT_, or dotnet user-secrets). Defaults are dev-friendly so the template runs out of the box; production hardens by flipping switches.

Section What it controls
Agent LLM provider (AzureOpenAI/OpenAI), model, endpoint, API key
Authentication API key for the X-API-Key header
Jwt OIDC bearer auth (authority, audience, issuers) — disabled by default
RateLimit InMemory or Redis, permits, window, Redis connection string
CostBudget Daily token cap per key — disabled by default
Resilience Retry attempts, backoff seconds
Telemetry Service name, OTLP endpoint, console exporter toggle
Conversation TTL minutes, max messages per conversation
Persistence InMemory · Sqlite · SqlServer · AzureSql · Postgres · MySql · Cosmos · Mongo. Same connection string for relational + Mongo; nested Cosmos.* / Mongo.* blocks for document stores
Retrieval Embedding model, vector store (InMemory or Qdrant), Qdrant host/port
Moderation None or AzureContentSafety, endpoint, max severity threshold

Conversation memory backends

IConversationStore ships with 8 backings, selected via Persistence:ConversationStore. Every backend honours Conversation:TtlMinutes and Conversation:MaxMessagesPerConversation, has a matching IAuditLog implementation, exposes a provider-aware /readyz health check, and idempotently creates its schema / containers / indexes on startup.

Backend ConversationStore value Required config Best for
In-memory InMemory (default) none Dev, single-instance, no durability
SQLite Sqlite Persistence:ConnectionString="Data Source=completeagent.db" Single-node prod, embedded, zero ops
SQL Server SqlServer Persistence:ConnectionString="Server=...;Database=...;..." Existing MSSQL fleet, on-prem or VM
Azure SQL AzureSql Persistence:ConnectionString="Server=tcp:<x>.database.windows.net,1433;Database=...;..." Azure-managed SQL with retry-on-failure baked in
PostgreSQL Postgres Persistence:ConnectionString="Host=...;Username=...;Password=...;Database=..." Open-source RDBMS, Aurora / RDS / Supabase / Neon
MySQL MySql Persistence:ConnectionString="Server=...;Database=...;Uid=...;Pwd=..." Existing MySQL / MariaDB fleet, Aurora MySQL
Cosmos DB Cosmos Persistence:Cosmos:ConnectionString or Persistence:Cosmos:AccountEndpoint + Persistence:Cosmos:AccountKey (+ Database, ConversationsContainer, AuditContainer) Global distribution, autoscale, per-doc TTL
MongoDB Mongo Persistence:ConnectionString="mongodb://..." (+ Persistence:Mongo:Database, ConversationsCollection, AuditCollection) Document-oriented, replica sets, Atlas

Implementation details:

  • Relational (Sqlite · SqlServer · AzureSql · Postgres · MySql) share EfCoreConversationStore + EfCoreAuditLog. RelationalSchemaBootstrapper calls EnsureCreatedAsync on startup. SQL Server, Azure SQL, PostgreSQL, and MySQL use their native datetimeoffset types; SQLite uses a value converter to ticks so range queries translate.
  • Cosmos DB uses the native Microsoft.Azure.Cosmos SDK. Container is partitioned by /conversationId. CosmosSchemaBootstrapper creates database + containers (TTL set to Conversation:TtlMinutes × 60s).
  • MongoDB uses the native MongoDB.Driver. MongoSchemaBootstrapper ensures a compound (conversationId, createdAt) index for fast load plus a TTL index on createdAt for auto-expiry.

Health checks are auto-registered per selected backend (RelationalDbHealthCheck / CosmosHealthCheck / MongoHealthCheck) and tagged ready, so /readyz fails fast when the configured store is unreachable.

To plug a custom backing (DynamoDB, Cassandra, FoundationDB, …) implement IConversationStore and register it instead of calling AddInfrastructure's default. The contract is three methods: LoadAsync, AppendAsync, ClearAsync.


Deploy

Local — docker-compose

export OPENAI_API_KEY=sk-...
export API_KEY=$(openssl rand -hex 16)
docker compose up --build

Wires agent → redis → qdrant → aspire-dashboard with persistent volumes for SQLite and Qdrant.

Service URL
Agent API http://localhost:8080
Scalar API Explorer (GitHub-themed, dark/light auto) http://localhost:8080/scalar
Aspire Dashboard (traces, metrics, logs) http://localhost:18888
Qdrant UI http://localhost:6333/dashboard

The bundled Aspire Dashboard is OTLP-native and shows resources, console output, structured logs, distributed traces (agent.run, LLM calls, tool calls), and per-token metrics — zero config. Swap to Grafana / Application Insights / Honeycomb for production by pointing COMPLETEAGENT_Telemetry__OtlpEndpoint at their gateway.

Kubernetes

docker build -t ghcr.io/<your-org>/completeagent:1.0.0 .
docker push ghcr.io/<your-org>/completeagent:1.0.0

# Edit deploy/k8s/secret.example.yaml with real values (or use External Secrets / Key Vault CSI).
kubectl apply -k deploy/k8s

Bundled manifests: namespace, configmap, secret.example, deployment (non-root, read-only FS, dropped capabilities, 3 probes), service, hpa (2–10 replicas on CPU+memory), networkpolicy (DNS, HTTPS, internal services only), kustomization.


Develop the template

# Pack
dotnet pack -c Release -o ./artifacts

# Install from local nupkg
dotnet new install ./artifacts/EncryptedTouhid.AgentFramework.Templates.0.1.0.nupkg

# Generate a sample and smoke-test
dotnet new et-complete-agent -n Demo -o /tmp/Demo
(cd /tmp/Demo && dotnet build && dotnet test)

# Uninstall when iterating
dotnet new uninstall EncryptedTouhid.AgentFramework.Templates

CI runs the same pack → install → generate → build → test flow on every push (.github/workflows/ci.yml).


Versions

Version
.NET SDK 10.0.x (via global.json, rollForward: latestMajor)
Microsoft.Agents.AI 1.6.2
Microsoft.Extensions.AI 10.6.0
Azure.AI.OpenAI 2.1.0
OpenTelemetry 1.15.x
EntityFrameworkCore.Sqlite 10.0.8
Qdrant.Client 1.18.1

Roadmap / not yet included

  • WebApplicationFactory-based integration tests
  • Conversation summarisation when history exceeds context budget
  • Embedding cache
  • Idempotency keys, circuit breaker
  • Document chunker / ingestion pipeline
  • Citations from RAG, hallucination scoring
  • MCP server tools, multi-step planner
  • Multimodal (image / audio)

See Roadmap discussion in repo issues to vote or contribute.


License

MIT — see LICENSE.

About

Complete Agent — Microsoft Agent Framework Template in .NET

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors