Five projects, one dependency arrow.
The .NET backend is split into five projects with a strictly enforced dependency hierarchy. Build that breaks the rule fails immediately, which is the whole point: dependencies always flow toward the API project, never away from it.
The dependency graph
Reading the graph: Infrastructure has zero project references and may be referenced by anyone. Data sits on top of Infrastructure. Agent and Auth both sit on top of Data + Infrastructure, but they don't see each other. Api sits on top of all four and is the only project that knows about HTTP.
Why this shape
- Infrastructure has no DB
- So that LangfuseClient, ITokenEncryptor, and Redis primitives can be reused by the MCP service without dragging EF Core along.
- Auth doesn't see Agent
- JWT issuance, OAuth callbacks, token encryption have nothing to do with the agent loop. Keeping them separate means changes in one cannot ripple into the other.
- Agent doesn't see Auth
- The agent loop reads
userId+tenantIdas plain inputs. It never decides who the user is. - Api is the only HTTP layer
- Endpoints, WebSocket handlers, DI wiring, and middleware live here. Lower layers are framework-agnostic.
- Tests live in one project
tests/AgenticIT.Tests/withUnit/,Integration/,Parity/. Integration tests use SQLite in-memory viaAgenticITWebAppFactory.
What lives where
AgenticIT.Infrastructure
AgenticITOptions.cs— strongly-typed config (LLM, OAuth, Langfuse, JWT, MCP, MaxToolTurns, …)EnvironmentVariableMapper.cs— flatOPENROUTER_API_KEY-style env vars → hierarchicalIConfigurationITokenEncryptor— symmetric encryption for stored OAuth / PAT / refresh tokens- Redis primitives,
LangfuseClient, helpers for connection-string parsing
AgenticIT.Data
AgenticITDbContext.cs— ~95 lines, all DbSets,OnModelCreatingappliesIEntityTypeConfiguration<T>from the assemblyEntities/— ~38 entities (TenantEntity, UserEntity, ChatEntity, ChatMessageEntity, ScheduledJobEntity, SkillEntity, …)Configuration/EntityConfigurations.cs— fluent EF mappings, JSONB converters, indexes (incl. partial unique indexes for skills)Repositories/— 40+ interfaces + implementations. Every method returnsDictionary<string, object?>(or a list)
AgenticIT.Agent
Orchestration/SmartOrchestrator.cs— planner + routing + trace scopeLoop/SingleAgentLoop.cs— single-agent tool loop (~86 KB)Orchestration/SpecialistRunner.cs— parallel specialists + synthesisTools/ToolRegistry.cs,Tools/ToolExecutor.cs— built-in catalog + dispatchMcp/—IMcpClientManager,McpSession, vBox token refresherInstructionModules/— embedded markdown skill bodies +InstructionModuleLoaderApproval/ApprovalGate.cs— in-memory destructive-tool gateMemory/— chat title, project summary, user summary, plan / reviewHeadless/HeadlessJobRunner.cs— scheduled job executionObservability/—IAgenticITTraceFactory,LangfuseTrace,TracingAnthropicClientCredits/CreditsService.cs— pre-call balance check + post-call usage record
AgenticIT.Auth
JwtService.cs— HMAC-SHA256 signing, claim layout, decode/validateOAuthService.cs— Microsoft / Google / GitHub code exchange + refreshVboxTokenRefresher.cs— refreshes vBox token on 401LocalAuthService.cs,TestUserSeeder.cs— basic auth for dev / testTokenEncryptionService.cs— concreteITokenEncryptorimplementation
AgenticIT.Api
Program.cs— ~78 KB. DI wiring, env-var mapping, OTel setup, schema bootstrap, additiveALTER TABLEstatements, endpoint registrationEndpoints/*— 30+RouteGroupBuilderextension files (chat, project, artifact, config, admin, scheduled, vbox, msgraph, …)WebSockets/ChatWebSocketHandler.cs— auth, channel attach, orchestrator launchWebSockets/StopWatchdog.cs— 5-second guarantee on user-initiated stops
Cross-cutting rules
Global ConfigureHttpJsonOptions with JsonNamingPolicy.SnakeCaseLower. C# SourceMessageId ↔ JSON source_message_id. Dictionary<string, object?> keys are explicit strings and unaffected by the policy.
Not thread-safe. Fire-and-forget Task.Run blocks must call IServiceScopeFactory.CreateAsyncScope() rather than capturing the request scope.
0 warnings, 0 errors. All 473 tests must pass. Default test run excludes integration tests via default.runsettings; run with --filter "FullyQualifiedName~AgenticIT.Tests.Integration" to opt in.
Where to dive
Agent system
Orchestrator → loop → specialists → synthesis, plus the trace and watchdog wiring.
→ 03.3Tools & MCP
The static catalog, the MCP client manager, dispatch order, destructive-tool gating.
→ 03.4Skills & instructions
The instruction modules that build the system prompt; the rename from Skills/.
→ 03.5Data layer
Why repositories return Dictionary, content envelopes, append-only history.
Auth
JWT layout, OAuth providers, vBox token refresh, test auth for dev.
→ 03.7Background work
Scheduled jobs, headless runner, reminders, proactive scans, suggestion engine.
→ 03.8Observability
Langfuse trace factory, generations, redaction, OpenTelemetry exporters.
→